【问题标题】:NotificationCenter observers prevent dealloc with ARCNotificationCenter 观察者阻止与 ARC 解除分配
【发布时间】:2013-11-16 17:18:17
【问题描述】:

我正在尝试调试我最近转换为使用 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 上给他们打电话。

但是,当注释掉观察者时,代码可以正常工作(并且视图卸载),但是对于观察者,它似乎不起作用并且视图保留在内存中。有什么建议吗?

【问题讨论】:

  • 在你的块中你引用了[self handle..],这将触发一个保留周期。我认为用他们的名字删除 oberserver 会更好。使用工具分配模板进行检查。
  • 有没有办法查看哪个引用持有该对象?它说“1”,但我找不到简单的方法来找出“1”的来源。

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


【解决方案1】:

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

【讨论】:

  • 感谢 Wain,这是一个有用的提示。当切换到 ARC 时,我应该对细节做更多的背景研究!
【解决方案2】:

调用时你并没有移除你的观察者

[[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;

     // ...
}

对 self 使用弱引用不会移除观察者。这将只允许释放您的视图控制器。但观察者块仍将在通知中心。并且每次都会调用它们。

【讨论】:

    猜你喜欢
    • 2011-12-11
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    相关资源
    最近更新 更多