You can use CFGetRetainCount
with Objective-C objects, even under ARC:
NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));
This is not particularly useful for debugging, though, for reasons amply described elsewhere. If you need to understand where an object is being retained and released, check out this answer for help using the Allocations instrument.
The only case I've found where examining the retain count is actually useful is in a dealloc
method, when something retains and autoreleases the object being deallocated. This will cause a crash later when the autorelease pool is drained. You can pinpoint the cause of this by checking the retain count before and after each message. In this way I discovered that the observationInfo
method (which is itself usually only useful for debugging) retains and autoreleases self
. However, even this sort of problem can usually be solved without examining the retain count, simply by wrapping the entire body of dealloc
in an @autoreleasepool
block.
However, the retain count can be used to learn about the implementation of some classes. (Only do this for entertainment or curiosity! Never rely on undocumented implementation details in production code!)
For example, try this immediately inside the @autoreleasepool
in main
:
NSNumber *n0 = [[NSNumber alloc] initWithInt:0];
NSLog(@"0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef)n0));
// Prints 2 in my test
So NSNumber
likely caches (or at least reuses) some instances. But not others:
n0 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n0));
// Prints 1 - I am the sole owner of this instance. There could be weak
// or unretained references to it, but no other strong references.
NSNumber *n1 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints 1 again. New instance with same value as prior instance.
// You could of course compare pointers to see that they are separate
// instances.
You can even discover that NSNumber
returns a singleton if you alloc
but don't initialize:
n1 = [NSNumber alloc];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints -1.
(Note that you can also learn many details about NSNumber
by looking at the Core Foundation source code, which is available at http://opensource.apple.com. But who knows what you might find if you look at the retain count of objects that aren't toll-free-bridged with objects in Core Foundation?)