removeObserver无法正常工作

时间:2013-06-10 11:21:41

标签: ios objective-c nsnotificationcenter

我有下一个代码:

@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一次&不能再添加Observer。

有什么问题?

修改 我尝试将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方法

中再次运行块

enter image description here

3 个答案:

答案 0 :(得分:24)

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

删除观察者的代码是错误的。对于基于块的观察者,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];

答案 1 :(得分:5)

e1985试图揭露的是addObserverremoveObserver来电未正确平衡。 VC初始化后只调用viewDidLoad一次,但每次将视图控制器移出屏幕时都会调用viewDidDisappear

要解决您的问题,您必须平衡addObserverremoveObserver来电,方法是将它们放在viewDidLoad中,将另一个放在dealloc中,或者 - 如e1985建议的那样 - 在viewDidAppear:viewDidDisappear:

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

因此,在您的情况下,[[NSNotificationCenter defaultCenter] removeObserver:self];不执行任何操作,因为self不是观察者。您应该在removeObserver:的返回值上调用addObserverForName:object:queue:usingBlock:,如图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

答案 2 :(得分:3)

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