使用ARC在双块中捕获自我

时间:2013-11-21 15:37:15

标签: objective-c automatic-ref-counting objective-c-blocks self

当我必须在一个区块中引用self时,我最近学会了这个技巧。

__weak MyObject *safeSelf = self;  
[self doWithCompletionBlock:^{

    HMFInventoryBatchItemsController *strongSelf = safeSelf;
    if (strongSelf) {
        [strongSelf doSomethingElse];
    }
}];

但我一直想知道,如果我在一个街区内有一个街区怎么办?我是否需要再次做同样的事情?

__weak MyObject *safeSelf = self;  
    [self doWithCompletionBlock:^{

        HMFInventoryBatchItemsController *strongSelf = safeSelf;
        if (strongSelf) {

            __weak MyObject *saferSelf = strongSelf;  
            [strongSelf doAnotherThingWithCompletionBlock:^{

                HMFInventoryBatchItemsController *strongerSelf = saferSelf;
                if (strongerSelf) {
                    [strongerSelf doSomethingElse];
                }
            }];
        }
   }];

或者这很好

__weak MyObject *safeSelf = self;  
    [self doWithCompletionBlock:^{

        HMFInventoryBatchItemsController *strongSelf = safeSelf;
        if (strongSelf) {

            [strongSelf doAnotherThingWithCompletionBlock:^{

                    [strongSelf doSomethingElse];

            }];
        }
   }];

2 个答案:

答案 0 :(得分:2)

好的答案是,这取决于。这通常是不安全的:

__weak MyObject *safeSelf = self;

[self doWithCompletionBlock:^{
      [safeSelf doAnotherThingWithCompletionBlock:^{
              [safeSelf doSomethingElse];
       }];
}];

原因在于,当你调用-doAnotherThingWithCompletionBlock时,如果该方法认为它会在self上保留一个引用,这是一个选择器通常会假设的,并且它会自我解除引用要访问ivars,那么你会崩溃,因为你实际上没有持有引用。

因此,您是否需要采用新的弱引用取决于您需要/想要的生命周期语义。

修改

顺便说一句,clang甚至会警告您可以在Xcode中使用CLANG_WARN_OBJC_RECEIVER_WEAK设置启用该问题(CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK在我们使用时也很有用)

答案 1 :(得分:0)

__block MyObject *safeSelf = self;

    [self doWithCompletionBlock:^{
          [safeSelf doAnotherThingWithCompletionBlock:^{
                  [safeSelf doSomethingElse];
           }];
   }];

希望它会做它应该做的事情。告诉编译器不要保留__weak MyObject *,无论它在哪个块范围内。事实是我没有经过测试。同时,如果它真的会保留MyObject *,我会感到惊讶。