首页 文章

是否有一种情况可以保留在ARC下的一个街区中的自我?

提问于
浏览
0

让我们说我的课看起来像

@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 回答

  • 0

    要回答 Headers 中的问题:是的,有很多理由这样做 . 您可能确定该对象将比该块更长,或者您可以创建一个保留周期,该周期将在稍后的特定时间手动中断 .

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

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

    [strongSelf._object doSomething];
    

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

    [strongSelf.object doSomething];
    

    在这种情况下,你会没事的,因为如果 strongSelfnil ,那么发送到 nil 的消息实际上什么都不做 .

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

    [strongSelf->_object doSomething];
    

    在这种情况下,如果strongSelf为零,您的程序将会爆炸,因为这不是向 nil 发送消息,而是取消引用空指针 . 如果您执行后者,则需要明确检查 nil .

    由于您不在块中访问 _queue ,因此该访问正常 . 任何直接访问块内的iVar都必须创建一个保留周期以确保对象仍然存活,或者它必须播放弱强舞并检查是否为零 .

    如果你在多行中使用该对象,你还需要做弱强舞,因为弱对象可以在访问之间解除分配(运行时保证如果__weak不是nil,并接受一条消息,它将保持不变活着,直到该消息被处理完毕) .

    [weakObject message1];
    // weakObject can become nil here
    [weakObject message2];
    
  • 2

    应该没问题,因为保留周期是暂时的 . 当调度的操作完成后,它将从队列中删除,因此不会再保留该块 .

相关问题