2012-09-10 27 views
3

在没有块创建强引用(并因此增加引用计数)的块内引用“自我”(和ivars)的正确方法是什么?参照自身和实例变量的块

例如,我发现下面的递增引用计数为“自我”:

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

为了避免上述情况,我一直在做以下操作:

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

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

回答

10

此外,间接引用自还创建了一个保留自我。例如,如果_ivar是一个实例变量,则访问它是对自我的隐式引用,因此以下内容也将保留自己。

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

此外,在您的weak例如扩大,它是确定将消息发送到弱引用。如果它是零,什么都不会发生。如果不是,那么编译器将生成代码,通过调用方法确保引用保持有效。

所以,这是罚款:

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

因为富要么是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; 
} 

将炸毁如果weakSelfnil

因此,在上述最后两种情况,你想要做的事,如:

__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

在你的第二个例子,我认为你的意思是'[weakSelf.foo doSomething]; [weakSelf.foo doSomethingElse];' –

+0

@ChristopherPickslay - 的确如此。谢谢! –

2

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