积木和额外的保留

时间:2013-12-16 21:52:33

标签: objective-c memory-management objective-c-blocks retain retaincount

当启用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。

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];
};