1

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

- (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

4

2 回答 2

2

并且文档retainCount这样说的:

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

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

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

回答你的问题:只有苹果可能知道为什么此时的 retainCount 是这样的。

于 2011-03-08T14:03:31.983 回答
2
_cancelBlock = [[cancelBlock copy] retain];

这会过度保留块;只是 - 复制它。


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

Note that a retainCount of zero is a logical impossibility in all cases.

于 2011-03-08T17:27:33.360 回答