removeObserver不起作用
我有下一个代码:
@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方法viewWillAppear
或viewWillDisappear
– 没有结果。 我添加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方法块
除了添加/删除观察者呼叫不正确的平衡,在其他答案中指出,还有另一个问题。
您的代码删除观察员是错误的。 对于基于块的观察者,必须将addObserver
的返回值作为addObserver
参数。 所以你应该添加一个属性
@property(nonatomic, strong) id observer;
去上课。 然后你添加观察者
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:NCDownloadComplete object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *n){ // ... }];
并删除它
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
e1985试图公开的是,你的addObserver
和removeObserver
调用没有适当的平衡。 viewDidLoad
在VC初始化后仅被调用一次,但每当视图控制器移出屏幕时,都会viewDidDisappear
。
为了解决你的问题,你必须平衡你的addObserver
和removeObserver
调用,或者在viewDidLoad
,另一个在dealloc
,或者 – 如e1985build议的 – 在viewDidAppear:
和viewDidDisappear:
。
编辑 :好的,所以你的问题来自于你使用addObserverForName:object:queue:usingBlock:
的事实addObserverForName:object:queue:usingBlock:
它不会注册self
作为观察者(如addObserver:selector:name:object:
如果你传递self
作为第一个参数) 。
所以在你的情况下, [[NSNotificationCenter defaultCenter] removeObserver:self];
什么都不做,因为self
不是观察者。 您应该调用removeObserver:
对addObserverForName:object:queue:usingBlock:
的返回值,如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:
添加观察者viewDidAppear:
并将其在viewDidDisappear:
删除viewDidDisappear:
。