ARC instance variable retain release

2019-03-03 18:35发布

问题:

If we have .h file like this:

@interface TestViewController : UIViewController {

    __weak NSObject *object;
}

@end

and methods in .m file like this:

- (void)viewDidLoad {

    [super viewDidLoad];
    NSObject *localObject = [[NSObject alloc] init];
    NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)localObject));
    object = localObject;
    NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)object));
    NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)localObject));
}

Then we get the following output for retain count:

1
2
1

My question is why does the retain count gets incremented to 2 on "object" when it is declared as "__weak" instance variable, furthermore "localObject" retain count remains 1. I think that's because of how ARC inserts retain/release but I am not sure.

回答1:

First of all the usual disclaimer: the absolute value of the retain count does not tell you anything useful, for more information see

  • http://whentouseretaincount.com
  • When to use -retainCount?

Now in your case, in the line

NSLog(@"%ld", CFGetRetainCount((__bridge CFTypeRef)object));

you read the value of a weak pointer, and the Clang/ARC documentation 4.2 Semantics states about that:

For __weak objects, the current pointee is retained and then released at the end of the current full-expression.

Therefore the object's retain count is increased by one while passed to CFGetRetainCount(). You can see that also in the generated assembly code:

movq    %rbx, %rdi
callq   _objc_retain
movq    %rax, %rbx
.loc    1 21 0                  
movq    %rbx, %rdi
callq   _CFGetRetainCount
movq    %r15, %rdi
movq    %rax, %rsi
xorb    %al, %al
callq   _NSLog
movq    _objc_release@GOTPCREL(%rip), %r12
movq    %rbx, %rdi
callq   *%r12