8

当我在视图控制器的方法中使用-addObserverForName: object: queue: usingBlock:for时,该方法最终不会被调用。 NSNotificationCenter-viewDidLoad:-dealloc

(当我删除-addObserverForName: object: queue: usingBlock:时,-dealloc再次调用。)

使用-addObserver: selector: name: object:似乎没有这个问题。我究竟做错了什么?(我的项目正在使用 ARC。)

下面是我的实现示例,以防我在这里做错了什么:

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  updateResult = YES;
                                              }];

提前感谢您的帮助。

我尝试添加以下内容(无济于事):

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    if ([self isMovingFromParentViewController]) {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
}
4

3 回答 3

17

updateResult是一个实例变量,可防止对象在该块保留时被释放。

换句话说,你有一个保留周期。对象保留块,块保留对象。

您将需要创建对该实例及其变量的弱引用或 unsafe_unretained 引用以失去该关系。

在通知块之前添加以下内容:

__unsafe_unretained YouObjectClass *weakSelf = self;

或(如果您使用的是 iOS5 及更高版本)

__weak YouObjectClass *weakSelf = self;

然后,在该块中,通过新的弱引用引用该对象:

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  weakSelf.updateResult = YES;
                                              }];

请注意,保留周期本身并不是一件坏事。有时您实际上希望它们发生。但在这些情况下,您可以确定循环将在特定时间后中断(例如动画块)。一旦块执行完毕并从堆栈中删除,循环就会中断。

于 2012-10-02T22:26:30.957 回答
6

这很可能是因为您有一个保留周期。

这通常是当您的块隐式保留自我并且自我以某种方式保留块时的情况。您将有一个保留周期,因为每个都保留另一个,因此它们的 retainCount 永远不会达到零。

您应该激活-Warc-retain-cycles将警告您此类问题的警告。

所以在你的情况下,你正在使用变量updateResult,我假设它是一个实例变量,这隐含地保留self。相反,您应该使用一个临时的弱变量来表示自我,并在您的块中使用它,这样它就不会被保留并且您会破坏保留循环。

__block __weak typeof(self) weakSelf = self; // weak reference to self, unretained by the block
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                              object:nil
                                               queue:nil
                                          usingBlock:^(NSNotification *note) {
                                              // Use weakSelf explicitly to avoid the implicit usage of self and thus the retain cycle
                                              weakSelf->updateResult = YES;
                                          }];
于 2012-10-02T22:29:06.967 回答
0

这不是保留周期。

NSNotificationCenter持有块,块是持有self。因为[NSNotificationCenter defaultCenter]是一个生活在所有应用程序生命周期中的单例,所以它是self间接的。

于 2017-11-19T16:21:47.560 回答