__Strong __weak __autorelease __unsafe_unretained _copy 关键字的本质和用法

1.__Strong  ARC 无效时,引用计数器加1,当超出作用域,引用为nil,由于未执行release 方法,对象还存在堆中,而此时引用销毁了,对象没有销毁,出现内存泄漏

ARC 有效时,引用计数器加1,当超出作用域,当系统判断引用为nil时,系统自动销毁对象。

ARC 情况下

2.__Weak  ARC 不持有对象,自动加入自动释放池autorelaesepool;

(1.)不持有对象,

例如 id __weak obj = [[ NSObject alloc ]init];系统警告,发现是以__weak 修饰的引用obj 系统会在创建好对象后,自动release掉。

(2.)自动加入自动释放池

例如 id __strong  obj =  [[ NSObject alloc ]init];

id __weak obj1=obj;{

伪代码如下:id__weak obj1 = obj,

id _autoreleasing tmp = obj1;    (加入自动释放池)

}

obj超出作用域,引用为nil,同时obj1引用为nil,(对象是否销毁要看系统什么时候销毁自动释放池,此时只是两个引用为nil)自动释放池此时持有对象,自动释放池销毁时销毁对象(系统在合适的时机销毁自动释放池)这个合适的时机就是当前的RunLoop循环结束。

3.__autorelease 将对象放入自动释放池,系统在合适的时机销毁自动释放池,同时销毁池内的对象。

4.__unsafe_unretained 不安全的所有权修饰符,如果用__unsafe_unretained 修饰的引用指向对象系统报错,同__weak,  例如 id __unsafe_unretained obj = [[ NSObject alloc ]init];系统  警告,

例如 id __strong  obj =  [[ NSObject alloc ]init];

id __unsafe_unretained obj1=obj;

obj 赋值给obj1,既不持有对象的强引用,也不持有对象的弱引用,当obj 超出作用域时,引用对象销毁,obj为nil,obj1为野指针。

ARC

1.__strong 的具体实现

id obj(默认strong)=  [[ NSObject alloc ]init];

id obj = objc_msgSend(NSObject,@selector(alloc));

objc_msgSend(obj,@selector(init));

当超出obj 的作用域时自动销毁

2.__weak 的具体实现

id obj(默认strong)=  [[ NSObject alloc ]init];

赋值为nil

id __weak obj1 = obj

obj1 = 0;

objc_storeWeak(&obj1,obj)

objc_storeWeak(&obj1,o)

(把第二参数的地址作为键值,将对参数的附有__weak 修饰符的变量注册到weak 表中,如果第二参数为0,记obj超出作用域或者obj为nil 则把变量地址从weak 表中删除,将obj1赋值为nil)

注册到自动释放池

objc_initWeak (&obj1,obj);

id temp = objc_loadWeakRetained(&obj1) (引用计数加1)

objc_autorelease(temp);

系统发现用__weak 修饰时通过 objc_loadWeakRetained 函数取出__weak 修饰符变量所引用的对象retain,然后放入自动释放池,objc引用超出作用域,指针销毁,obj1销毁,对象等自动释放池释放时销毁。


5copy 

copy 分为三种情况

1.当修饰,NSMutableString NSMutableArry 等可变的字符串或者数组时,必须用copy,因为strong 是单纯增加对象的引用计数,改变的同时会同时改变源对象,而copy 是做的深拷贝,改变对象的同时,对源对象没有影响,所以必须用copy。

2.当修饰不可变字符串或者数组,字典时分为两种情况


1.当传入的对象也为不可变对象时,用copy和strong 没有区别,例如

__Strong __weak __autorelease __unsafe_unretained _copy 关键字的本质和用法_第1张图片

1.

NSString *textStr = @“TextString”;

self.StrStrong = textStr;

self.strCopy   =textStr;

当textStr 的值改变时,self.StrStrong或者self.StrStrong 的值并不会因为textStr的值改变而发生改变,因为不可变字符串在代码区,例如当textStr = @“TextString” 时,textStr 指向的是TextString 的首地址,而当textStr = @“TextString1”,textStr 指向的是TextString1 的首地址

记当textStr = @“TextString”;self.StrStrong = textStr;self.StrStrong = strCopy;时,他们三个的地址都是指向“TextString”的首地址,当self.StrStrong = @"TextChange" 时,textStr和self.strCopy还是指向TextString,所以他们三个当中任意一个的值改变都不会影响到对方,所以用Strong和copy 没有任何区别.

2.

NSMutableString *textStr =  [NSMutableString stringWithString:@"textStr"];

self.StrStrong = textStr;(指向的是对象textStr,强引用,引用计数器加1)

self.strCopy= textStr;(对对象textStr 的一次深拷贝)

当textStr 的值改变时,self.StrStrong 的值会发生改变因为self.StrStrong和textStr指向的是同一个对象,而self.strCopy对textStr做的是深拷贝,所以值不会发生改变。所以在进行赋值操作时如果接收的对象是可变对象,也必须用copy。

注意:因为在进行赋值操作时,我们并不能确定传递的是可变字符串、字典、数组,还是不可变字符串、字典、数组。所以我们应该统一用copy 这样就可以避免出现对象改变的情况,bug出现的几率会大大降低,所以建议不管是可变不可变时都统一用copy

你可能感兴趣的:(__Strong __weak __autorelease __unsafe_unretained _copy 关键字的本质和用法)