A method defined by the NSObject protocol allows you to obtain the current retain count for an object:
- (NSUInteger)retainCount
However, ARC has deprecated this method. In fact, the compiler will throw an error if you try to call it when using ARC, just as it does with such methods as retain, release, and autorelease. Even though this method is officially deprecated, it is often misunderstood, and its use should be avoided. If you are not using ARC, which you really should be, it’s still possible to use this method without getting a compiler error. So it is still important to understand why this method is to be avoided.
The problem is, though, that the absolute retain count is often completely irrelevant and not what you need to know. Even if you use this method only for debug purposes, it’s usually not at all helpful.
while ([object retainCount])
{
[object release];
}
If the object was also in an autorelease pool at the time, when that pool is drained, the object is further released, and a crash will certainly occur.
// Large "retain counts" of some objects (singletons)
NSString *string = @"Some string";
NSLog(@"string retainCount = %lu", [string retainCount]);
NSNumber *numberI = @1;
NSLog(@"numberI retainCount = %lu", [numberI retainCount]);
NSNumber *numberF = @3.141f;
NSLog(@"numberF retainCount = %lu", [numberF retainCount]);
string retainCount = 18446744073709551615
numberI retainCount = 9223372036854775807
numberF retainCount = 1
The first number is 264 – 1 and the second number is 263 – 1. The retain counts of these objects are both very large because they are representing singleton objects. NSString is implemented as a singleton object, if possible. It is possible if the string is a compile- time constant, as in the example. In this case, the compiler makes a special object, placing the data for the NSString object within the application binary, and uses that instead of creating an NSString object at runtime. NSNumber does a similar thing, using a concept known as tagged pointers for certain types of values.
This optimization is done only for certain cases, though, which is why the floating-point number in the example has a retain count of 1, as it does not use this optimization.
In addition, the retain counts of singletons such as these never change. Retains and releases are no-ops.
// Showing retain count might not necessarily be what you expect
id object = [self createObject];
[opaqueObject doSomethingWithObject:object];
NSLog(@"retainCount = %lu", [object retainCount]);
What is the retain count? It could be anything. The call to doSomethingWithObject: may have added the object to multiple collections, retaining it in the process. Or the call may have retained the object multiple times and autoreleased it multiple times, some of which are still pending an autorelease pool drain. The retain count is therefore unlikely to be useful to you.