【发布时间】:2012-07-27 11:37:09
【问题描述】:
我使用块已经有一段时间了,但我觉得在 ARC 和非 ARC 环境中的内存管理方面我有些怀念。我觉得更深入的理解会让我避免很多内存泄漏。
AFNetworking 是我在特定应用程序中主要使用 Blocks。大多数时候,在操作的完成处理程序中,我会执行“[self.myArray addObject]”之类的操作。
在启用 ARC 和未启用 ARC 的环境中,“self”将根据this article from Apple 保留。
这意味着每当调用 AFNetworking 网络操作的完成块时,self 会保留在该块内,并在该块超出范围时释放。我相信这适用于 ARC 和非 ARC。我已经运行了 Leaks 工具和 Static Analyzer,以便我可以发现任何内存泄漏。没有任何显示。
但是,直到最近我才偶然发现了一个我无法理解的警告。我在这个特定的例子中使用了 ARC。
我有两个实例变量指示网络操作的完成和失败
@property (nonatomic, readwrite, copy) SFCompletionBlock completionBlock;
@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;
@synthesize failureBlock = _failureBlock;
@synthesize operation = _operation;
在代码的某处,我这样做:
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id
responseObject) {
NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
_failureBlock(error);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"nothing");
}];
Xcode 抱怨调用failureBlock 的那一行,消息“Capturing "self" strong in this block is likely to result in a retain cycle。我相信Xcode是对的:失败块保留self,self持有它的块的自己的副本,因此两者都不会被释放。
但是,我有以下问题/意见。
1) 如果我将 _failureBlock(error) 更改为“self.failureBlock(error)”(不带引号),编译器将停止抱怨。这是为什么?这是编译器遗漏的内存泄漏吗?
2) 一般来说,在使用作为实例变量的块时,在启用 ARC 和非启用 ARC 的环境中使用块的最佳做法是什么?似乎在 AFNetworking 中的完成和失败块的情况下,这两个块是 not 实例变量,因此它们可能不属于我上面描述的保留周期类别。但是当在 AFNetworking 中使用进度块时,可以做些什么来避免像上面那样的保留循环?
我很想听听其他人对 ARC 和非 ARC 的想法,包括内存管理的块和问题/解决方案。我发现这些情况很容易出错,我觉得有必要对此进行一些讨论以澄清问题。
我不知道这是否重要,但我使用 Xcode 4.4 和最新的 LLVM。
【问题讨论】:
标签: objective-c memory-management automatic-ref-counting objective-c-blocks afnetworking