Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 用圆弧捕捉双块中的自我_Objective C_Automatic Ref Counting_Objective C Blocks_Self - Fatal编程技术网

Objective c 用圆弧捕捉双块中的自我

Objective c 用圆弧捕捉双块中的自我,objective-c,automatic-ref-counting,objective-c-blocks,self,Objective C,Automatic Ref Counting,Objective C Blocks,Self,我最近学会了这个技巧,当我必须在一个块内引用self时 __weak MyObject *safeSelf = self; [self doWithCompletionBlock:^{ HMFInventoryBatchItemsController *strongSelf = safeSelf; if (strongSelf) { [strongSelf doSomethingElse]; } }]; 但我一直在想,如果一个街区内有一个街区呢?我

我最近学会了这个技巧,当我必须在一个块内引用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];

            }];
        }
   }];

希望它能做它通常应该做的事情。告诉编译器不要保留_弱MyObject*,无论它在哪个块范围内。事实是我没有测试。同时,如果它真的能保留MyObject*

我会感到惊讶。好的答案是,这要看情况而定。一般来说,这样做是不安全的:

__weak MyObject *safeSelf = self;

[self doWithCompletionBlock:^{
      [safeSelf doAnotherThingWithCompletionBlock:^{
              [safeSelf doSomethingElse];
       }];
}];
原因是,当您调用
-dootherthingWithCompletionBlock
时,如果该方法认为它在
self
上持有一个引用(选择器通常假定该引用),并且它取消对self的引用以访问IVAR,那么您将崩溃,因为您实际上没有持有一个引用

因此,您是否需要接受新的弱引用取决于您需要/想要的生存期语义

编辑:


顺便说一句,clang甚至有一个关于这个问题的警告,你可以在Xcode中使用
clang\u WARN\u OBJC\u RECEIVER\u WEAK
设置来启用它(
clang\u WARN\u OBJC\u REPEATED\u OF\u WEAK
也很有用)

为什么要用HMFInventoryBatchItemsController*strongSelf=safeSelf重新分配self;因为self是块的所有权?除非你想访问它的ivar,否则你不必在块中进行强引用。我发现这篇文章是作为引用的。有什么方法可以测试它吗?你可以使用retaincount并观察safeself在块中是否有+1计数(当然,制作一个简单的代码来保证“self”不保留在其他地方。)。第二种方法是在使用块调用后释放对象(假设块是IVAR,而不是函数范围的本地块)。如果从未调用dealloc,则块保留了块所有权对象。“弱”的目的实际上是为了防止这种情况。你可能指的是“方法”而不是“选择器”。你可能还表示“引用IVAR”而不是“取消引用IVAR”,表示
self->someIvar;)事实上,我刚刚改写了我的回答。这并不不安全,因为self拥有block对象。在这种情况下,self永远不会是块对象堆栈中的悬空指针。如果你不这样做,赛尔夫将永远不会被释放,同样的块。唯一可能发生这种情况的是,当您忘记释放一个拥有的异步块时,这无论如何都是不好的。使用ARC now,这种情况永远不会发生。顺便说一下,应该使用“块”而不是“弱”语义。
__weak MyObject *safeSelf = self;

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