iOS-Strong/Copy修饰词

作者: cdcyd | 来源:发表于2017-07-11 14:31 被阅读136次

    在iOS中,string是用strong修饰还是用copy修饰?它们有什么区别呢?本文主要就来讨论这两个问题,在此之前,我们需要知道两个术语,浅拷贝和深拷贝

    浅拷贝:指对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的指针需要赋值,要不然会成为野指针
    深拷贝:指对对象具体内容复制,重新分配对象的内存地址,拷贝结束之后,两个对象虽然值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉

    上代码,测试一下

    NSString *str = @"test";
    NSString *copyStr = [str copy];
    NSMutableString *mutStr = [str mutableCopy];
        
    NSLog(@"指针地址:str:%p--copyStr:%p--mutStr:%p",&str,&copyStr,&mutStr);
    NSLog(@"内存地址:str:%p--copyStr:%p--mutStr:%p",str,copyStr,mutStr);
    

    运行结果:

    指针地址:str:0x16fb31678--copyStr:0x16fb31670--mutStr:0x16fb31668
    内存地址:str:0x1002d4080--copyStr:0x1002d4080--mutStr:0x1c024af80
    

    可以看出:copy实现了一次浅拷贝,mutableCopy实现了一次深拷贝
    实际上,对于copy和mutableCopy我们可以得出下表的结论


    理解了copy作用,我们就不难理解属性中的copy和strong了,实际上在属性中copy比strong多了一步,即在setter方法中

    - (void)setName:(id)name{
        _name = [name copy];
    }
    

    举个例子:假设有这样一段代码

    @property(copy)id obj;
    
    self.obj = object;
    
    此时obj是什么呢?有下面两种情况:
    1. object是不可变对象,将会把object浅拷贝一次,赋值给obj
    2. object是可变对象,将会把object深拷贝一次,赋值给obj
    如果obj是用strong修饰的,就没有拷贝一说了,将会直接把object赋值给obj
    
    在内存计数方面
    strong 会使object引用计数+1,obj的引用计数为1
    copy   如果object是不可变对象,object引用计数+1,obj的引用计数为1
           如果object是可变对象,会将object深拷贝一份,object的引用计数不会变,obj的引用计数为1
    

    综上所述,我们可以得出以下结论

    1. 当属性本身是可变对象时
      此时只能用strong修饰,因为如下图,下图中,name属性经过setter时,得到的永远是不可变对象,当调用可变方法时,就会崩溃


    2. 当属性的赋值来源是可变对象时,如下图,看日志输出,发现当使用strong时,来源发生改变,属性值会跟着发生改变,当实用copy时,来源发生改变,属性不会跟着变


    3. 当属性的赋值来源是不可变对象时,如下图,发现strong和copy并没有什么区别



      所以我们在选用修饰词时,我们要根据,属性本身是否可变,对属性赋值的来源是否可变,属性是否需要跟随来源的变化而变化等情况来选用属性的修饰词,不过,在实际开发中,大多数情况都是用copy

    相关文章

      网友评论

        本文标题:iOS-Strong/Copy修饰词

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