虽然用了很久的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.实例变量
被__weak修饰的变量,被加入到weak表中,以它所指向的对象的地址作为key。在对象被释放时,会将weak表中的所有注册weak变量移除并置为nil。
①.被声明时
{
id__weak wkOBJC = objc;
}
==>>
{
id wkOBJC =nil;
objc_initWeak(&wkOBJC,objc);
objc_destoryWeak(&wkOBJC);
}
其中objc_initWeak跟objc_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;
}
==>>
{
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.
后记:有纰漏再补充~