NotificationCenter观察员阻止了ARC的dealloc

时间:2013-11-16 17:18:18

标签: ios iphone objective-c automatic-ref-counting nsnotificationcenter

我正在尝试调试我最近转换为使用ARC的项目。 我很难确定为什么没有释放对象并留在内存中(有一种简单的方法可以查看哪个引用将对象保存在内存中?)

通知中心链接似乎存在一个问题。 在viewDidLoad上我注册了三个通知:

[notificationCenter addObserverForName: kAudioPlaybackStart
                                object: nil
                                 queue:[NSOperationQueue mainQueue]
                            usingBlock:^(NSNotification *note) {
                                [self handle_PlaybackStateStart:nil];
                            }];
[notificationCenter addObserverForName: kAudioPlaybackStop
                                object: nil
                                 queue:[NSOperationQueue mainQueue]
                            usingBlock:^(NSNotification *note) {
                                [self handle_PlaybackStateStop:nil];
                            }];
[notificationCenter addObserverForName: kAudioPlaybackPause
                                object: nil
                                 queue:[NSOperationQueue mainQueue]
                            usingBlock:^(NSNotification *note) {
                                [self handle_PlaybackStatePause:nil];
                            }];

然后,当viewController完成后,我调用一个函数unLoad:

- (void) unLoad {
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    _mediaPlayerHelper = nil;
    _article = nil;
    _tableView = nil;
}

我有一个单独的函数的原因是除非释放所有对象,否则不会调用viewDidUnload,所以我需要一些东西来释放它们。目前我在viewDidDisappear上调用它们。

但是,在注释掉观察者时,代码工作正常(并且查看卸载),但是观察者看起来不起作用并且视图保留在内存中。有什么建议吗?

2 个答案:

答案 0 :(得分:6)

因为您正在使用带有块参数的通知方法,并且您在块中使用了对self的强引用。您应该使用使用回调选择器的观察方法(因此没有捕获)或创建__weakself的引用以在块中使用。

答案 1 :(得分:1)

调用

时,您不会删除观察者
[[NSNotificationCenter defaultCenter] removeObserver:self];

您必须不通过self,而是返回addObserverForName:...方法的值。

像这样的东西。对于所有的观察者。

@property (strong, nonatomic) id audioStartObserver;

-(void)viewDidLoad
{
    [super viewDidLoad];
    self.audioStartObserver = [notificationCenter addObserverForName: kAudioPlaybackStart
                            object: nil
                             queue:[NSOperationQueue mainQueue]
                        usingBlock:^(NSNotification *note) {
                            [self handle_PlaybackStateStart:nil];
                        }];
     // ...
 }

- (void) unLoad {
    [[NSNotificationCenter defaultCenter] removeObserver:self.audioStartObserver];
    self.audioStartObserver = nil;

     // ...
}

使用弱引用自我不会删除观察者。这将只允许取消分配您的视图控制器。但是观察者块仍然在通知中心。每次都会打电话给他们。