我已经使用块一段时间了,但我觉得在ARC和非ARC环境中都会错过内存管理方面的一些事情。我认为更深入的理解将使我避免许多内存泄漏。
在特定应用程序中,AFNetworking是我主要使用块的工具。大多数时候,在操作的完成处理程序内部,我会执行类似于“[self.myArray addObject]”这样的操作。
根据Apple的这篇文章,在ARC和非ARC启用的环境中,“self”将被保留下来。
这意味着每当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的那一行,显示“在此块中强烈捕获“self”可能导致保留循环。Xcode是正确的:失败块会保留self,而self持有自己的块的副本,因此两者都不会被释放。
然而,我有以下问题/观察结果。
1)如果将_failureBlock(error)更改为“self.failureBlock(error)”(不包含引号),编译器就会停止抱怨。为什么?这是编译器遗漏的内存泄漏吗?
2)通常,在使用实例变量块时,无论是ARC还是非ARC启用的环境中,最佳实践是什么?看起来,在AFNetworking中完成和失败块不是实例变量,因此它们可能不属于我上面描述的保留循环类别。但是,在AFNetworking中使用进度块时,如何避免像上面那样的保留循环呢?
我很想听听其他人对ARC和非ARC与块以及内存管理问题/解决方案的想法。我发现这些情况容易出错,我觉得有必要讨论一下这个问题以澄清事情。
我不知道这是否重要,但我使用具有最新LLVM的Xcode 4.4。