当启用ARC时,以下代码通过调用objc_retain()和objc_retainBlock()导致obj保留两次块。(因此,在块定义之后,retainCount变为3。)
我检查了obj不在自动释放池中,并且在方法结束时有两个objc_release()调用obj。 (我知道计数保留没有意义,但我正在检查objc_retain()调用,而不是几乎不检查保留计数。) 这背后的理由是什么?
-(void)myMethod
{
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj %@ retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
void (^myBlock)(void) = ^()
{
NSLog(@"obj %@ retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
};
NSLog(@"obj %@ retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
myBlock();
}
仅仅保留一次obj以便通过块捕获它是不够的?
注意:此外,当我删除myBlock变量并调用它时,所以只使用^(){...}定义并且永远不能调用该定义,obj仍然保留objc_retain(),这看起来很奇怪。我正在使用XCode 4.3.2。
答案 0 :(得分:13)
www.whentouseretaincount.com - 即不要使用retainCount
,因为它不会引起混淆。即使是学习内脏。
如果您想知道块如何以及何时保留对象,您应该查看编译器,运行时和阻塞运行时源。一切都可以。
块可能会也可能不会保留对象。具体来说,块只能在复制块时保留对象(只要对象引用不是__weak
)。
类似地,但正交地,ARC的保留/释放行为基于编译器的优化级别而改变。特别是,DEBUG(-O0)代码往往有很多保留/释放。 -Os(优化)代码将有许多优化出来。
答案 1 :(得分:3)
请阅读:http://whentouseretaincount.com/
你不应该使用保留计数,写它的苹果开发人员反对它,许多聪明的人建议反对它,我告诉你不要使用它。
至于保留周期,其优良做法是在块范围之外具有弱属性:
__weak typeof(obj) weakObj = obj;
void (^block)(void) = ^{
[weakObj method];
};