参考self和instance vars的块

时间:2012-09-10 18:24:25

标签: objective-c ios objective-c-blocks

在块内引用'self'(和ivars)而没有块创建强引用(从而增加引用计数)的正确方法是什么?

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

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

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

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

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

2 个答案:

答案 0 :(得分:10)

此外,间接引用自我也会在自我中产生一种保留。例如,如果_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]; } 之间进行调用,这可能不是您想要的:

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

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

另一方面,如果您通过弱引用直接访问iVars,则必须执行弱强舞,因为此代码:

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 } ,则

会爆炸。

因此,在上面的最后两种情况中,你想做类似的事情:

{{1}}

当然,如果您实际直接访问iVars,iVar情况只是一个问题...

答案 1 :(得分:2)

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