让我们说我的课看起来像
@interface MyClass {
MyObject* _object;
dispatch_queue_t _queue;
}
-(void)myBlocksUsingMethod;
@end
忽略初始化队列的语义,现在我实现
-(void)myBlockUsingMethod {
dispatch_async(_queue, ^{
[_object doSomething];
});
}
如上面的代码所示,在块中保留自己好吗?
我可以重写像
这样的块-(void)myBlockUsingMethod {
__weak MyClass* weakSelf = self;
dispatch_async(_queue, ^{
MyClass* strongSelf = weakSelf;
[strongSelf._object doSomething];
});
}
但是现在是否有必要在这种情况下测试strongSelf == nil
,因为我的_queue
是我保留的对象的iVar?
此外,如果我的doSomething
方法将另一个引用self
的块推送到同一队列,会发生什么?这会导致保留周期吗?
答案 0 :(得分:2)
回答标题中的问题:是的,有很多理由这样做。您可能确定该对象将比该块更长,或者您可能想要创建一个保留周期,该周期将在稍后的特定时间手动中断。
但是,在你的代码中,你做错了。第一种方法(创建对self的隐式强引用的方法)应生成警告。
第二个不应该编译。你有这个:
[strongSelf._object doSomething];
正在调用名为_object
的属性,我怀疑是这种情况。所以,也许你的意思是:
[strongSelf.object doSomething];
在这种情况下,您会没事的,因为如果strongSelf
为nil
,则发送给nil
的邮件实际上无效。
或者,如果没有财产,也许你真的是这个意思:
[strongSelf->_object doSomething];
在这种情况下,如果strongSelf为nil,程序将会爆炸,因为这不会向nil
发送消息,而是取消引用空指针。如果您执行后者,则需要明确检查nil
。
由于您未访问块中的_queue
,因此该访问权限正常。任何直接访问块内的iVar都必须创建一个保留周期以确保对象仍然存活,或者它必须播放弱强舞并检查是否为零。
如果你在多行中使用对象,你还需要做弱强舞,因为弱对象可以在访问之间解除分配(运行时保证如果__weak不是nil,并接受一条消息,那么它将保持活着,直到该消息被处理完毕。)
[weakObject message1];
// weakObject can become nil here
[weakObject message2];
答案 1 :(得分:0)
应该没问题,因为保留周期是暂时的。当调度的操作完成后,它将从队列中删除,因此不再保留该块。