重新认识ARC

虽然用了很久的ARC,感受了代码简洁。但是对ARC底层实现并不了解。

今天抽空研究了下,做些简单地总结。

一、__strong

1.局部变量

①.对于局部变量来说,在超出作用域的地方由编译器自动插入release。

{

id__strong objc = [NSObject new];

}

==>>  (大概转化为)

{

id objc =objc_msgSend(objc_getClass("NSObject"),@selector(new));

objc_release(objc);

}

②.在非ARC返回的autorelease类型的方法

{

id__strong objc = [NSMutableArray array];

}

==> (在Blog手码大概代码,如有错误还望指出)

{

id objc =objc_msgSend(NSMutableArray,@selector(array));

objc_retainAutoreleaseReturnValue(objc);

objc_release(objc);

}

这里比①多了一步 objc_retainAutoreleaseReturnValue(objc);对autorelease类型做了一个不retain。

我们来猜测 [NSMutableArray array] 内部的实现

+(id)array

{

return{ [NSMutableArray alloc] init];

}

==> 转化后

{

id tmp =objc_msgSend(NSMutableArray,@selector(alloc)));

  objc_msgSend(tmp,@selector(init));

return objc_autoreleaseReturnValue(tmp);

}

这里边对tmp做了objc_autoreleaseReturnValue操作,这个操作跟objc_autorelease()是有区别的。objc_autoreleaseReturnValue会检查命令栈(具体叫什么名字有点迷糊了)如果发现紧接其后调用了objc_retainAutoreleaseReturnValue方法,就不会将tmp加入到autoreleasepool中。而objc_autorelease会直接把对象放入到pool中。

所以:类方法返回的对象如果被__strong修饰,其实并没有加入到pool中,算是编译器优化~

2.实例变量

我以前一直以为是在dealloc中被ARC插入release的。后来发现是编译器利用了C++的一个特性。C++生成了个xxxDestu..(这个    文件名记不清楚了,稍后补上),编译器会 在这里处理实例变量的释放。当然按照之前的理解也没什么大碍~~


二、__weak

被__weak修饰的变量,被加入到weak表中,以它所指向的对象的地址作为key。在对象被释放时,会将weak表中的所有注册weak变量移除并置为nil。

①.被声明时

{

id__weak wkOBJC = objc;

}

==>>

{

id wkOBJC =nil;

objc_initWeak(&wkOBJC,objc);

objc_destoryWeak(&wkOBJC);

}

其中objc_initWeakobjc_destoryWeak内部都是使用的objc_storeWeak();

objc_initWeak

 ==>>  

{

id tmp = 0;

return objc_storeWeak(&tmp,objc)

}

对应的objc_destoryWeak

==>>

{

objc_storeWeak(&wkOBJC,0)

}

__weak在被声明时,通过objc_storeWeak加入到注册表中。

②.在被使用时

{

id __weak wkOBJC = objc;

NSLog(@"%@",wkOBJC);

}

==>>

{

id wkOBJC = nil;

objc_initWeak(&wkOBJC,objc);

objc_destoryWeak(wkOBJC);

id tmp =objc_loadWeakRetained(&wkOBJC);

objc_autorelease(tmp);

NSLog(@"%@",tmp);

objc_destroyWeak(&wkOBJC)

}

可以看到在使用__weak修饰的变量时,会使用一个中间变量retain一次,然后再加入到autoreleasepool。如果多次使用,就会生成大量的autorelease对象到pool中。作为优化,可使用 id __strong sOBJC = wkOBJC.



后记:有纰漏再补充~








你可能感兴趣的:(arc,__weak,__strong)