Reputation: 13
In ARC environment, I allocate a dynamic array of which each element is a pointer to NSObject*. Then use CFGetRetainCount to get the retain count of the NSObject. The result comes out as expected. However, when I change the NSObject to NSString, the retain count comes out as a large number, which confused me so much. I have searched google, but can't find any valuable information. So, can anyone explain? Appreciate any help.
first code snippet:
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject* __strong *arr = nil;
arr = (id __strong *)calloc(2, sizeof(id));
*arr = [[NSObject alloc]init];
*(arr + 1) = [[NSObject alloc]init];
NSLog(@"--->retainCount:%lu -->%@", CFGetRetainCount((__bridge CFTypeRef)*arr), *arr);
//output:--->retainCount:1 --><NSObject: 0x100103a00>
*arr = nil;
*(arr + 1) = nil;
free(arr);
}
return 0;
}
second code snippet:
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* __strong *arr = nil;
arr = (id __strong *)calloc(2, sizeof(id));
*arr = [[NSString alloc]initWithString:@"str_01"];
*(arr + 1) = [[NSString alloc]init];
NSLog(@"--->retainCount:%lu \n-->%@", CFGetRetainCount((__bridge CFTypeRef)*arr), *arr);
//output:--->retainCount:1152921504606846975 -->str_01
*arr = nil;
*(arr + 1) = nil;
free(arr);
}
return 0;
}
the NSLog outputs confuse me: why the retain count is not "1" in the second code snippet? is there any different compared with the first code snippet?
Upvotes: 0
Views: 402
Reputation: 10219
The thing is that several Foundation classes in Objective C - like NSString
, NSArray
, NSNumber
- don't behave like "normal" user classes. For example, NSNumber
is typically a so-called tagged pointer - a pointer at a "illegal" address (which is not divisible by 4 or 8) and represents the value and not an address. NSString
, NSArray
... are implemented as so-called class clusters, which is a mechanism that exchanges the internal implementation inside the initializer (e.g. returns a different object than the one that was allocated by the alloc
call). Most often, NSString
s are interned / atomized, which is a way to allow quick comparisons etc. by simple pointer comparision (instead of strncmp
-like byte-by-byte comparisons).
To fall a long story short: You should never rely on retain counts, this is just an implementation detail of the reference counting mechanism.
Upvotes: 1