Objective c 用圆弧捕捉双块中的自我
我最近学会了这个技巧,当我必须在一个块内引用self时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]; } }]; 但我一直在想,如果一个街区内有一个街区呢?我
__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];
}];
}];