0

假设我的班级看起来像

@interface MyClass {
    MyObject* _object;
    dispatch_queue_t _queue;
}
-(void)myBlocksUsingMethod;
@end

忽略初始化队列的语义,现在我实现

-(void)myBlockUsingMethod {
    dispatch_async(_queue, ^{
        [_object doSomething];
    });
}

正如上面的代码所示,在块中保留 self 可以吗?

我可以像这样重写块

-(void)myBlockUsingMethod {
    __weak MyClass* weakSelf = self;
    dispatch_async(_queue, ^{
        MyClass* strongSelf = weakSelf;
        [strongSelf._object doSomething];
    });
}

但是现在是否有必要测试strongSelf == nil在这种情况下是否考虑到 my_queue是我保留的对象的 iVar?

另外,如果我的doSomething方法是将引用的另一个块推self送到同一个队列中会发生什么?这会导致保留周期吗?

4

2 回答 2

2

回答标题中的问题:是的,有很多理由这样做。您可能肯定知道该对象的寿命会超过该块,或者您可能希望创建一个保留循环,该循环将在以后的特定时间手动中断。

但是,在您的代码中,您正在做一些非常错误的事情。第一种方法(创建对 self 的隐式强引用的方法)应生成警告。

第二个不应该编译。你有这个:

[strongSelf._object doSomething];

这是调用一个名为的属性_object,我怀疑是这种情况。所以,也许你的意思是:

[strongSelf.object doSomething];

在这种情况下,你会没事的,因为 if strongSelfis nilthen 发送到的消息nil实际上什么都不做。

或者,如果没有属性,也许你真的是这个意思:

[strongSelf->_object doSomething];

在这种情况下,如果 strongSelf 为 nil,您的程序将会崩溃,因为这不是向空指针发送消息nil而是取消引用空指针。如果你做后者,你需要nil明确地检查。

由于您不在_queue该块中访问,因此该访问很好。对块内 iVar 的任何直接访问都必须创建一个保留循环以确保对象仍然存在,或者它必须播放弱-强-dance 并检查 nil。

如果您在多行中使用该对象,您还需要执行弱强舞蹈,因为弱对象可以在访问之间释放(运行时保证如果 __weak 不是 nil 并接受消息,它将保持直到该消息被处理为止)。

[weakObject message1];
// weakObject can become nil here
[weakObject message2];
于 2012-09-07T22:58:33.707 回答
0

应该没问题,因为保留周期是暂时的。当分派的动作完成后,它会从队列中移除,因此不再保留该块。

于 2012-09-07T22:40:49.803 回答