让我们说我的课看起来像
@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
的块推送到同一队列,会发生什么?这会导致保留周期吗?
2 回答
要回答 Headers 中的问题:是的,有很多理由这样做 . 您可能确定该对象将比该块更长,或者您可以创建一个保留周期,该周期将在稍后的特定时间手动中断 .
但是,在您的代码中,您正在做一些非常错误的事情 . 第一种方法(创建对self的隐式强引用的方法)应生成警告 .
第二个不应该编译 . 你有这个:
它正在调用一个名为
_object
的属性,我怀疑是这种情况 . 所以,也许你的意思是:在这种情况下,你会没事的,因为如果
strongSelf
是nil
,那么发送到nil
的消息实际上什么都不做 .或者,如果没有 property ,也许你真的是这个意思:
在这种情况下,如果strongSelf为零,您的程序将会爆炸,因为这不是向
nil
发送消息,而是取消引用空指针 . 如果您执行后者,则需要明确检查nil
.由于您不在块中访问
_queue
,因此该访问正常 . 任何直接访问块内的iVar都必须创建一个保留周期以确保对象仍然存活,或者它必须播放弱强舞并检查是否为零 .如果你在多行中使用该对象,你还需要做弱强舞,因为弱对象可以在访问之间解除分配(运行时保证如果__weak不是nil,并接受一条消息,它将保持不变活着,直到该消息被处理完毕) .
应该没问题,因为保留周期是暂时的 . 当调度的操作完成后,它将从队列中删除,因此不会再保留该块 .