6

我有下一个代码:

@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]

这个VCviewDidLoad一开始用过一次&不能再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 方法中运行块

在此处输入图像描述

4

3 回答 3

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];
于 2013-06-10T12:07:23.853 回答
5

e1985 试图揭露的是你的addObserverremoveObserver电话没有得到适当的平衡。viewDidLoad在 VC 初始化后只调用一次,但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:,如文档中所示:

返回值

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

所以你的代码应该看起来像:

// 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
于 2013-06-10T11:41:14.407 回答
3

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

于 2013-06-10T11:25:01.220 回答