我在课堂上得到了这段代码:
- (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
的相同值?
答案 0 :(得分:2)
retainCount
的{{3}}说明了这一点:
重要:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法。
要了解您必须遵守的内存管理的基本规则,请阅读“内存管理规则”。要诊断内存管理问题,请使用合适的工具:
LLVM / Clang静态分析仪通常可以在运行程序之前发现内存管理问题 仪器应用程序中的Object Alloc仪器(参见仪器用户指南)可以跟踪对象分配和销毁 Shark(参见Shark用户指南)还描述了内存分配(在程序的许多其他方面)。
回答你的问题:只有苹果可能知道为什么此时的retainCount就像它一样。
答案 1 :(得分:2)
_cancelBlock = [[cancelBlock copy] retain];
过度保留该块;只是复制它。
由于Blocks可以根据所采取的操作在运行时更改表单,并根据实现细节在编译时更改类型,因此各种Block类通常将retainCount
视为无意义的生成器。在某些情况下,这意味着总是返回1。
请注意,retainCount
为零在所有情况下都是不可能的。