cso*_*iou 6 memory-management objective-c objective-c-blocks automatic-ref-counting afnetworking
我一直在使用块一段时间,但我觉得在ARC和非ARC环境中都有一些我想念的内存管理.我觉得更深刻的理解会让我失去许多内存泄漏.
AFNetworking是我在特定应用程序中主要使用Blocks.大多数情况下,在操作的完成处理程序中,我执行类似"[self.myArray addObject]"的操作.
在ARC和非ARC启用的环境中,根据Apple的这篇文章,将保留"self" .
这意味着每当调用AFNetworking网络操作的完成块时,self将保留在该块内,并在该块超出范围时释放.我相信这适用于ARC和非ARC.我已经运行了泄漏工具和静态分析器,以便我可以发现任何内存泄漏.没有显示任何.
然而,直到最近,我偶然发现了一个我无法弄清楚的警告.我在这个特定的例子中使用ARC.
我有两个实例变量,表明网络操作的完成和失败
@property (nonatomic, readwrite, copy) SFCompletionBlock completionBlock;
@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;
@synthesize failureBlock = _failureBlock;
@synthesize operation = _operation;
Run Code Online (Sandbox Code Playgroud)
在代码的某处,我这样做:
[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");
}];
Run Code Online (Sandbox Code Playgroud)
.Xcode的抱怨调用failureBlock线,以"捕获'自我’强烈该块的消息很可能导致保留周期,我相信Xcode是正确的:不良区保留自我,自我拥有自己的副本块,所以两者都不会被解除分配.
但是,我有以下问题/意见.
1)如果我将_failureBlock(错误)更改为"self.failureBlock(error)"(不带引号),编译器将停止抱怨.这是为什么?这是编译器错过的内存泄漏吗?
2)通常,在使用作为实例变量的块时,在ARC和非ARC启用的环境中使用块的最佳实践是什么?似乎在AFNetworking中的完成和故障块的情况下,这两个块不是实例变量,因此它们可能不属于我上面描述的保留周期类别.但是当将进度块用于AFNetworking时,可以采取哪些措施来避免像上面那样的保留周期?
我很想听听其他人对ARC和非ARC的看法,包括带有内存管理的块和问题/解决方案.我发现这些情况容易出错,我觉得有必要对此进行一些讨论以便清理.
我不知道它是否重要,但我使用Xcode 4.4和最新的LLVM.
1)如果我将_failureBlock(错误)更改为"self.failureBlock(error)"(不带引号),编译器将停止抱怨.这是为什么?这是编译器错过的内存泄漏吗?
两种情况都存在保留周期.如果您的目标是iOS 5+,则可以向自己传递一个弱引用:
__weak MyClass *weakSelf;
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
if (weakSelf.failureBlock) weakSelf.failureBlock(error);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"nothing");
}];
Run Code Online (Sandbox Code Playgroud)
现在self不会被保留,如果在调用回调之前它被释放,则回调是no-op.但是,当在后台线程上调用回调时,它可能正在进行释放,因此这种模式可能会偶尔发生崩溃.
2)通常,在使用作为实例变量的块时,在ARC和非ARC启用的环境中使用块的最佳实践是什么?似乎在AFNetworking中的完成和故障块的情况下,这两个块不是实例变量,因此它们可能不属于我上面描述的保留周期类别.但是当将进度块用于AFNetworking时,可以采取哪些措施来避免像上面那样的保留周期?
大多数时候,我认为最好不要在实例变量中存储块.如果你从类中的方法返回块,你仍然会有一个保留周期,但它只存在从调用方法到释放块的时间.因此,它会阻止您的实例在块执行期间被释放,但保留周期在块释放时结束:
-(SFCompletionBlock)completionBlock {
return ^(AFHTTPRequestOperation *operation , id responseObject ) {
[self doSomethingWithOperation:operation];
};
}
[self.operation setCompletionBlockWithSuccess:[self completionBlock]
failure:[self failureBlock]
];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4891 次 |
| 最近记录: |