美文网首页iOS 面试
__Strong  __weak  __autorelease

__Strong  __weak  __autorelease

作者: 啥啥啥啥啥 | 来源:发表于2016-04-18 16:40 被阅读148次

    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 没有区别,例如

    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

        本文链接:https://www.haomeiwen.com/subject/wkjalttx.html