retainCount in blocks show extrange behavior

2019-03-02 08:31发布

I got the this code in a class:

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

The output for this NSLog()'s are:

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

The documentation for the copy method says this:

Special Considerations

If you are using managed memory (not garbage collection), this method retains the new object before returning it. The invoker of the method, however, is responsible for releasing the returned object.

So. Way the output of the NSLog() always show the same value for retainCount?

2条回答
Anthone
2楼-- · 2019-03-02 08:57
_cancelBlock = [[cancelBlock copy] retain];

That over-retains the block; just -copy it.


Since Blocks can change form at runtime based upon actions taken and change type at compile time based on implementation details, the various Block classes generally treat retainCount as the nonsense generator that it is. In some cases, this will mean returning 1 always.

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

查看更多
可以哭但决不认输i
3楼-- · 2019-03-02 09:18

and the documentation for retainCount says this:

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

To understand the fundamental rules of memory management that you must abide by, read “Memory Management Rules”. To diagnose memory management problems, use a suitable tool:

The LLVM/Clang Static analyzer can typically find memory management problems even before you run your program.
The Object Alloc instrument in the Instruments application (see Instruments User Guide) can track object allocation and destruction.
Shark (see Shark User Guide) also profiles memory allocations (amongst numerous other aspects of your program).

To answer your question: Only apple might know why the retainCount at this point is like it is.

查看更多
登录 后发表回答