3

在块内没有创建强引用(并因此增加引用计数)的块内引用“self”(和 ivars)的正确方法是什么?

例如,我发现以下增加了“self”的引用计数:

^(id sender) {
    [self.navigationController popViewControllerAnimated:YES];
}

为了规避上述情况,我一直在做以下事情:

__weak WhateverController *weakSelf = self;
^(id sender) {
    [weakSelf.navigationController popViewControllerAnimated:YES];
};

是的,我意识到这是伪代码。

4

2 回答 2

10

此外,对 self 的间接引用也会对 self 产生保留。例如,如果_ivar是一个实例变量,访问它是对 self 的隐式引用,因此以下内容也将保留 self。

^(id sender) {
    [_ivar popViewControllerAnimated:YES];
}

此外,为了扩展您的weak示例,可以向弱引用发送消息。如果它为零,则不会发生任何事情。如果不是,则编译器将生成代码,以确保通过调用方法来确保引用保持有效。

所以,这很好:

__weak Foo *weakSelf = self;
^(id sender) {
    [weakSelf.foo doSomething];
}

因为 foo 要么是nil要么不是,它保证在整个执行过程中保持非零doSomething

但是,以下内容是不可取的,因为self可能会nil在通话之间进行,这可能不是您想要的:

__weak Foo *weakSelf = self;
^(id sender) {
    [weakSelf.foo doSomething];
    [weakSelf.foo doSomethingElse];
}

在这种情况下,您可能希望在块内创建自己的强引用,以便在整个块的执行过程中具有一致的值。

另一方面,如果你直接通过弱引用访问 iVar,你必须跳弱强之舞,因为这段代码:

__weak Foo *weakSelf = self;
^(id sender) {
    weakSelf->_foo = bar;
}

weakSelf如果是的话会爆炸nil

因此,在上述最后两种情况下,您希望执行以下操作:

__weak Foo *weakSelf = self;
^(id sender) {
    Foo *strongSelf = weakSelf;
    if (!strongSelf) return;
    // Now, do anything with strongSelf, as it is guaranteed to be around
}

当然,iVar 的情况只有在您实际直接访问 iVar 时才会出现问题......

于 2012-09-10T19:10:52.050 回答
2

苹果的符号是 sself 但除此之外 - 你很好。
在非弧项目中,使用以下代码来防止“自我”被块保留:
__block id sself = self

于 2012-09-10T18:29:45.047 回答