块中的retainCount显示了外部行为

时间:2011-03-08 13:29:45

标签: objective-c objective-c-runtime objective-c-blocks

我在课堂上得到了这段代码:

- (void)cancel {
    if (_cancelBlock)
        _cancelBlock();
}
- (void)overrideCancelWithBlock:(void(^)(void))cancelBlock {
    [_cancelBlock release];
    NSLog(@"AsyncOperation-overrideCancelWithBlock-[cancelBlock retainCount]=%lu (before)", [cancelBlock retainCount]);
    _cancelBlock = [[cancelBlock copy] retain];
    NSLog(@"AsyncOperation-overrideCancelWithBlock-[_cancelBlock retainCount]=%lu (after)", [_cancelBlock retainCount]);
}

- (void)dealloc
{
    NSLog(@"AsyncOperation-dealloc-[_cancelBlock retainCount]=%lu (before)", [_cancelBlock retainCount]);
    [_cancelBlock release];
    NSLog(@"AsyncOperation-dealloc-[_cancelBlock retainCount]=%lu (after)", [_cancelBlock retainCount]);
    [super dealloc];
}

此NSLog()的输出是:

 AsyncOperation-overrideCancelWithBlock-[cancelBlock retainCount]=1 (before)
 AsyncOperation-overrideCancelWithBlock-[_cancelBlock retainCount]=1 (after)
 AsyncOperation-dealloc-[_cancelBlock retainCount]=1 (before)
 AsyncOperation-dealloc-[_cancelBlock retainCount]=1 (after) 

copy方法的文档说明了这一点:

  

特别注意事项

     

如果您使用的是托管内存(不是   垃圾收集),这种方法   之前保留新对象   归还它。调用者   然而,方法是负责的   释放返回的对象。

因此。 NSLog()的输出总是显示retainCount的相同值?

2 个答案:

答案 0 :(得分:2)

retainCount的{​​{3}}说明了这一点:

  

重要:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法。

     

要了解您必须遵守的内存管理的基本规则,请阅读“内存管理规则”。要诊断内存管理问题,请使用合适的工具:

     

LLVM / Clang静态分析仪通常可以在运行程序之前发现内存管理问题   仪器应用程序中的Object Alloc仪器(参见仪器用户指南)可以跟踪对象分配和销毁   Shark(参见Shark用户指南)还描述了内存分配(在程序的许多其他方面)。

回答你的问题:只有苹果可能知道为什么此时的retainCount就像它一样。

答案 1 :(得分:2)

_cancelBlock = [[cancelBlock copy] retain];

过度保留该块;只是复制它。


由于Blocks可以根据所采取的操作在运行时更改表单,并根据实现细节在编译时更改类型,因此各种Block类通常将retainCount视为无意义的生成器。在某些情况下,这意味着总是返回1。

请注意,retainCount为零在所有情况下都是不可能的。