我在将一些 NSOperation 代码转换为 ARC 时遇到困难。我的操作对象使用一个完成块,该完成块又包含一个更新主线程上的 UI 的 GCD 块。因为我从操作对象自己的完成块内部引用操作对象,所以我使用 __weak 指针来避免内存泄漏。但是,当我的代码运行时,指针已经设置为 nil。
我已将范围缩小到此代码示例。有人知道我哪里出错了,以及实现这一目标的正确方法吗?
NSOperationSubclass *operation = [[NSOperationSubclass alloc] init];
__weak NSOperationSubclass *weakOperation = operation;
[operation setCompletionBlock:^{
dispatch_async( dispatch_get_main_queue(), ^{
// fails the check
NSAssert( weakOperation != nil, @"pointer is nil" );
...
});
}];
另一种选择是:
NSOperationSubclass *operation = [[NSOperationSubclass alloc] init];
__weak NSOperationSubclass *weakOperation = operation;
[operation setCompletionBlock:^{
NSOperationSubclass *strongOperation = weakOperation;
dispatch_async(dispatch_get_main_queue(), ^{
assert(strongOperation != nil);
...
});
}];
[operationQueue addOperation:operation];
我假设您还将操作对象添加到 NSOperationQueue 中。在这种情况下,队列将保留一个操作。它可能也在完成块的执行期间保留它(尽管我还没有找到有关完成块的官方确认)。
但在完成块内部会创建另一个块。该块将在稍后的某个时间点运行,可能是在 NSOperations 的完成块运行结束之后。当这个情况发生时,operation
将被队列释放并且weakOperation
将nil
。但是,如果我们从操作的完成块创建对同一对象的另一个强引用,我们将确保operation
当第二个块运行时将存在,并避免保留循环,因为我们不捕获operation
块的变量。
Apple 在中提供了此示例过渡到 ARC 发行说明 http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html请参阅最后一个代码片段使用生命周期限定符避免强引用循环部分。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)