下面的代码在
非arc下:obC = 1 ob1C = 2
在arc下:obC = 1 ob1C = 1
为什么在arc下 ob1C是1,本人觉得应该也是2啊,不是调用了setter吗?setter不是先release旧值,在retain新值的吗?
(_ob和ob1都是用strong声明的)
_ob = [[NSObject alloc] init];
self.ob1 = [[NSObject alloc] init];
非arc下:obC = 1 ob1C = 2
在arc下:obC = 1 ob1C = 1
为什么在arc下 ob1C是1,本人觉得应该也是2啊,不是调用了setter吗?setter不是先release旧值,在retain新值的吗?
(_ob和ob1都是用strong声明的)
_ob = [[NSObject alloc] init];
self.ob1 = [[NSObject alloc] init];
NSInteger obC = CFGetRetainCount((__bridge CFTypeRef)_ob);
NSInteger ob1C = CFGetRetainCount((__bridge CFTypeRef)_ob1);
解决方案
50
其实是原因是你用 ARC 的话,编译器在 self.ob1 = [[NSObject alloc] init]; 之后就对 obj1 做了一次 release 了
代码如下:
代码如下:
#import <Foundation/Foundation.h> @interface C : NSObject @property (nonatomic, strong) NSObject *obj; @property (nonatomic, strong) NSObject *obj1; @end @implementation C - (instancetype)init { self = [super init]; _obj = [[NSObject alloc] init]; self.obj1 = [[NSObject alloc] init]; NSInteger obC = CFGetRetainCount((__bridge CFTypeRef)_obj); NSInteger ob1C = CFGetRetainCount((__bridge CFTypeRef)_obj1); NSLog(@"%d, %d", obC, ob1C); return self; } @end int main(int argc, char *argv[]) { @autoreleasepool { C *c = [[C alloc] init]; } }
我们来看类 C 的 init 方法的汇编代码
ARC 编译后得到的汇编代码(这里借助了下 Hopper 生成的伪码,帮助我们看懂汇编代码)
void * -[C init](void * self, void * _cmd) { rax = var_20; rax = [[rax super] init]; var_8 = rax; objc_storeStrong(0x0, rax); rax = [NSObject alloc]; rax = [rax init]; rcx = var_8->_obj; var_8->_obj = rax; [rcx release]; rax = [NSObject alloc]; rax = [rax init]; var_40 = rax; [var_8 setObj1:rax]; [var_40 release]; NSLog(@"%d, %d", CFGetRetainCount(var_8->_obj), CFGetRetainCount(var_8->_obj1)); var_48 = [var_8 retain]; objc_storeStrong(var_8, 0x0); rax = var_48; return rax; }
可以看到 set 完成后,都调用了一次 release,所以后面输出的结果是1,1
相对的非 ARC 的汇编代码如下:
void * -[C init](void * self, void * _cmd) { rax = var_20; var_8 = [[rax super] init]; var_8->_obj = [[NSObject alloc] init]; rax = [NSObject alloc]; rax = [rax init]; [var_8 setObj1:rax]; NSLog(@"%d, %d", CFGetRetainCount(var_8->_obj), CFGetRetainCount(var_8->_obj1)); rax = var_8; return rax; }
可以看到对象在创建后丢给了 set 方法,Retain Count +1,但是在之后并没有调用 release 方法,所以这里输出的结果就是1,2了