【问题标题】:removeObserver not workingremoveObserver 不工作
【发布时间】:2013-06-10 11:21:40
【问题描述】:

我有下一个代码:

@implementation SplashViewVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.splashView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Default.png"]];
    self.activityIndicator.originY = 355.f;
    [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
        NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];        
        [self.activityIndicator stopAnimating];
        if (errorCode == ERROR_CODE_NO_CONNECTION) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil];
            [alertView show];
        } else if (errorCode == 0) {
            [self dismissViewControllerAnimated:YES completion:nil];
        }
    }];
    [self downloadData];
}

- (void)downloadData
{
    [self.activityIndicator startAnimating];
    [[Server sharedServer] getMovieData];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [self downloadData];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewDidDisappear:animated];
}

@end

所以我把断点放在viewDidLoad 方法的开头,在viewDidDisappear 中。当我启动应用程序时首先转到viewDidload,下载后转到viewDidDisappear

但在我的应用程序中,我再次下载数据并发布notification: NSDownloadComplete。在这个 VC 中它是有效的,但我后来删除了:

[[NSNotificationCenter defaultCenter] removeObserver:self]

这个VC一开始使用viewDidLoad一次&不能再addObserver。

怎么了?

编辑 我尝试将 addObserver 方法放入 viewWillAppearviewWillDisappear - 没有结果。 我在之前添加NSLog(@"addObserver");

 [[NSNotificationCenter defaultCenter] addObserverForName...

在 viewDidLoad 中

然后写

- (void)viewDidDisappear:(BOOL)animated
{
    NSLog(@"removeObserver");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewDidDisappear:animated];
}

在日志中我看到:

2013-06-10 14:32:05.646 myApp[9390:c07] addObserver
2013-06-10 14:32:06.780 myApp[9390:c07] removeObserver

怎么了?

编辑 2 您可以看到必须删除观察者,但它再次在 addObserver 方法中运行块

【问题讨论】:

  • 那段代码是复制粘贴的吗?我只是想知道,因为您的 viewDidLoad 只有 3 行,然后有一些语句不是任何方法。那是无效的;)
  • @HAS 一切正常,除了我的问题 =)
  • 抱歉,这不是 ;) self.activityIndicator.originY = 355.f; 之后的花括号是错误的。删除,您将获得有效代码;)
  • @HAS 我编辑,错误,抱歉
  • 只在 dealloc 中 removeObserver

标签: ios objective-c nsnotificationcenter


【解决方案1】:

除了没有正确平衡添加/删除观察者调用之外,在其他答案中指出,还有另一个问题。

您删除观察者的代码是错误的。对于基于块的观察者,addObserver返回值 必须作为removeObserver 的参数给出。所以你应该添加一个属性

@property(nonatomic, strong) id observer;

上课。然后你添加观察者

self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
    // ...
}];

并删除它

[[NSNotificationCenter defaultCenter] removeObserver:self.observer];

【讨论】:

  • 非常感谢 Martin,您的解决方案运行良好。
【解决方案2】:

e1985 试图揭露的是您的 addObserverremoveObserver 调用没有正确平衡。 viewDidLoad 仅在 VC 初始化后调用一次,而 viewDidDisappear 则在每次视图控制器移出屏幕时调用。

要解决您的问题,您必须平衡您的 addObserverremoveObserver 调用,方法是在 viewDidLoaddealloc 中进行调用,或者 - 如 e1985 建议的 - 在 viewDidAppear:viewDidDisappear: .

编辑:好的,所以你的问题来自于你使用addObserverForName:object:queue:usingBlock: 没有将self 注册为观察者的事实(如果你通过selfaddObserver:selector:name:object: 会这样做作为第一个参数)。

所以在你的情况下,[[NSNotificationCenter defaultCenter] removeObserver:self]; 什么都不做,因为self 不是观察者。你应该在addObserverForName:object:queue:usingBlock:的返回值上调用removeObserver:,如图in the doc

返回值

充当观察者的不透明对象。

所以你的代码应该是这样的:

// header file .h
@interface SplashViewVC : UIViewController

@property (strong, nonatomic) id downloadCompleteObserver;

@end

// implementation file .m
@implementation SplashViewVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // [...] snip

    self.downloadCompleteObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){
        NSInteger errorCode = [n.userInfo[@"errorCode"] integerValue];        
        [self.activityIndicator stopAnimating];
        if (errorCode == ERROR_CODE_NO_CONNECTION) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Some problem with server" delegate:self cancelButtonTitle:@"try again" otherButtonTitles:nil];
            [alertView show];
        } else if (errorCode == 0) {
            [self dismissViewControllerAnimated:YES completion:nil];
        }
    }];
    [self downloadData];
}

// [...] snip

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self.downloadCompleteObserver];
    [super dealloc];
}

@end

【讨论】:

  • 我在 viewDidAppear 中移动:但没有结果 =(
  • 那请把问题解释清楚一点。什么是“不工作”?
  • 我添加了一个屏幕,您可以在其中看到在 removeObserver 方法之后调用的块。
【解决方案3】:

您使用的模式不正确。您应该在viewDidAppear: 中添加观察者并在viewDidDisappear: 中删除它。

【讨论】:

  • 或在viewWillAppear:添加观察者
  • @e1985 帮不上忙。和 viewWillAppear:也帮不上忙
猜你喜欢
  • 1970-01-01
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多