When I use __weak pointer refer to an NSObject, the unexpected retainCount is shown.
The test code and result are as the image below.

Here is the code:
id obj1 = [[NSObject alloc] init];
id __weak obj2 = obj1;
NSLog(@"obj1: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1)); // line 31
NSLog(@"obj2: %ld", CFGetRetainCount((__bridge CFTypeRef)obj2)); // line 32
NSLog(@"obj1 again: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1)); // line 33
So~ My confusion is that, obj2's retainCount is expected to 1, Why retainCount is 2?
I've read from book: the __weak pointer registered the object to the autoreleasepool, so the retain count + 1.
However, obj1 and obj2 refer to the same memory address, in that case, the obj1's retainCount should also become 2. But, it still remain in 1.
I know retainCount is unreliable but I'm so curious about how this came. (My environment is Xcode 8.3.3, iOS 10.3)
Greatly appreciate if anyone can explain this to a beginner :)
The exact value of the retain count is generally an implementation detail that depends on the compiler, the Objective-C language runtime, and any other libraries involved (like Foundation). But it's reasonable to wonder why it behaves this way, as long as you don't depend on the behavior.
Either your book is wrong, or you misunderstood it. Using
__weakdoesn't put the object in the autoreleasepool.Here is what is happening on line 32 (the one with the
@"obj2: %ld"format string).To safely pass an object reference to a function or method (like
NSLog), it has to be a strongly-held reference. So the compiler generates a call toobjc_loadWeakRetainedonobj2. This function atomically increments the retain count of the object and returns the reference. Thus the retain count of the object goes from 1 to 2 before the object reference is passed toNSLog.Then, after
NSLogreturns, the compiler generates a call toobjc_release. Thus the retain count goes back down from 2 to 1 by the thirdNSLog.If you want to be sure what's happening, look at the assembler output of the compiler. You can ask Xcode to show it to you:
Here's the relevant part of the assembly:
Line 16 is (in my test) the one that uses
obj2. You can see the call toobjc_loadWeakRetainedbefore the call toCFGetRetainCount, and the call toobjc_releaseafterNSLogreturns.