弧,块和保留周期

使用ARC处理目标为4.0和5.0的iOS项目。

遇到与块有关的问题,ARC以及从块外部引用对象。 这是一些代码:

__block AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionBlock:^ { if ([operation isCancelled]) { return; } ... do stuff ... operation = nil; }]; 

在这种情况下,编译器给出了一个警告,即在块中使用“操作”将导致保留周期。 在ARC下,__block现在保留该variables。

如果我添加__unsafe_unretained,编译器立即释放对象,所以很明显,这将无法正常工作。

我瞄准4.0,所以我不能使用__weak。

我试着做这样的事情:

 AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; __block __unsafe_unretained AFHTTPRequestOperation *weakOperation = operation; 

但是虽然弱操作不是零,但是在块内部没有任何属性被填充。

鉴于上面列出的项目限制,处理这种情况的最佳方法是什么?

假设进度保证,保留周期可能正是你想要的。 你明确地在程序段末尾打破了保留循环,所以它不是一个永久的保留循环:当程序段被调用时,循环被打破。

但是,如果您还有别的操作,可以将引用存储到__weak__unsafe_unretainedvariables中,然后在块中使用该引用。 除非由于某种原因需要在块中更改variables的绑定,否则不需要__block限定variables。 由于您没有保留周期,所以您不需要为弱variables分配任何内容。

这似乎是Conrad Stoll在“ 块,操作和保留周期”中描述的问题,但是他的写作忽略了一些重要的问题:

  • __block看起来像苹果公司推荐的方式,以避免在MRC模式下强烈引用捕获的variables,但在ARC模式中完全没有必要。 在这种情况下,在ARC模式中完全没有必要; 在MRC模式下也是不必要的,虽然轻量级的解决方法更加冗长: void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; } void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; }
  • 在ARC模式下,你需要一个强大的引用(所以你可以将它添加到队列中)和一个弱/ unsafe_unretained参考

最简单的解决scheme如下所示:

 AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; AFHTTPRequestOperation * __unsafe_unretained unretainedOperation = operation; [operation setCompletionBlock:^ { if ([unretainedOperation isCancelled]) { return; } ... do stuff ... }]; 

即使你打破了引用循环, Block也没有理由首先保留AFHTTPRequestOperation (假设操作保持自己的状态直到完成处理程序完成,这并不总是保证,但通常是真的,由ARC如果它被称为使用self进一步调用堆栈)。

最好的解决方法似乎是更新到最新的AFNetworking ,它将操作传递到块作为参数。