ARC,块和保留周期
使用ARC处理目标为4.0和5.0的iOS项目。ARC,块和保留周期
遇到与块,ARC和块外部引用对象相关的问题。下面是一些代码:
__block AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlock:^ {
if ([operation isCancelled]) {
return;
}
... do stuff ...
operation = nil;
}];
在这种情况下,编译器会发出警告,在块是用“操作”将会导致保留周期。在ARC下,__block现在保留该变量。
如果我添加__unsafe_unretained,编译器会立即释放对象,所以很明显,这是行不通的。
我针对4.0,所以我不能使用__weak。
我试图做这样的事情:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
__block __unsafe_unretained AFHTTPRequestOperation *weakOperation = operation;
但同时weakOperation不为零,没有它的属性被填充时,块内。
考虑到上面列出的项目限制,处理这种情况的最佳方法是什么?
假设进度保证,保留周期可能正是你想要的。你明确地在块的末尾打破了保留周期,所以它不是一个永久的保留周期:当块被调用时,周期被打破。
但是,如果您还有其他操作可以保留操作,则可以将参考存储到__weak
或__unsafe_unretained
变量中,然后使用块中的参考。除非由于某种原因需要在块中更改变量的绑定,否则不需要__block
- 对变量进行限定;由于您没有保留周期来破坏,所以您不需要为弱变量分配任何内容。
这似乎是由康拉德·斯托尔在Blocks, Operations, and Retain Cycles描述的问题,但他的书面记录错过了几个要点:
-
__block
貌似避免在MRC捕获变量很强的参考的苹果推荐的方式模式,但在ARC模式下完全没有必要。在这种情况下,在ARC模式下完全没有必要;也正是在MRC模式不必要虽然重量更轻的解决办法是更详细:void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; }
- 在ARC模式下,你既需要很强的参考(这样你就可以将其添加到队列)和弱/ unsafe_unretained参考
最简单的办法是这样的:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFHTTPRequestOperation * __unsafe_unretained unretainedOperation = operation;
[operation setCompletionBlock:^ {
if ([unretainedOperation isCancelled]) {
return;
}
... do stuff ...
}];
即使你打破参考周期,没有理由阻止保留AFHTTPRequestOperation
摆在首位(假设操作会保持自身活着直到t他完成处理程序完成,这并不总是保证但通常如果使用ARC进一步调用堆栈上的self
引用由ARC假定和假定。
最好的修复程序似乎是更新到latest AFNetworking,它将操作作为参数传递到块中。
__block不是完全不必要的。默认情况下,所有由块保留的变量都是const内部的,所以你不能改变它们的值。这里__block来拯救。 –
我已经有了'没有保留周期'的东西,我甚至都没有按照你描述的方式去思考。咄。下一个问题 - 任何方式来沉默编译器警告?它会让我发疯。 – Hunter
请参阅Clang用户手册中的[“通过Pragma控制诊断”](http://clang.llvm.org/docs/UsersManual.html#diagnostics_pragmas)。你只需要弄清楚哪个警告标志要忽略。 –
这是'#pragma clang diagnostic ignored'-Warc-retain-cycles“',由by。 –