美文网首页
iOS内存管理:属性修饰符Strong和Copy

iOS内存管理:属性修饰符Strong和Copy

作者: Pulan | 来源:发表于2018-04-13 15:40 被阅读0次

    ARC是通过编译器自动加入Retain、Copy和Release等方法调用来实现内存管理,仍然以引用计数为基础。

    1. Strong和Copy的区别

    依据ARC的实现原理,属性被Strong或Copy修饰决定在其Setter方法中调用Retain还是Copy。

    //使用strong修饰的strongString属性的Setter方法
    - (void)setStrongString:(NSMutableString *)strongString
    {
        if (strongString != _strongString) {
            [_strongString release];
            _strongString = [strongString retain];
        }
    }
    
    //使用copy修饰的copytoString属性的Setter方法
    - (void)setCopytoString:(NSMutableString *)copytoString
    {
        if (copytoString != _copytoString) {
            [_copytoString release];
            _copytoString = [copytoString copy];
        }
    }
    
    2. Strong和Copy在什么情况下使用

    (1) Strong
    strong一般用于非容器类对象。会增加引用计数。相当与Mrc中的Retain。
    (2)Copy
    copy用于容器类对象,比如NSString、NSArray、NSDictionary,或其他实现NSCopying、NSMutableCopying协议的对象。对于Setter传入对象为不可变对象时,功能与strong相同。对于Setter方法传入对象为可变对象时,会进行深拷贝,不增加引用计数。

    3. 测试实例和结果
    //声明两个String类型的属性,一个用strong修饰,一个用copy修饰
    @property (nonatomic, strong) NSString *strongString;
    @property (nonatomic, copy) NSString *copytoString;
    

    //赋值值类型为可变对象
    - (void)test
    {
        NSMutableString *str = [NSMutableString stringWithFormat:@"123"];
        NSLog(@"初始str = %@ p = %p &p = %p",str,str,&str);
        
        self.copytoString = str;
        self.strongString = str;
        
        [str appendString:@"123"];
        NSLog(@"拼接后str = %@ p = %p &p = %p",str,str,&str);
        
        NSLog(@"copytoString = %@ p = %p class = %@",self.copytoString,_copytoString,NSStringFromClass([_copytoString class]));
        NSLog(@"strongString = %@ p = %p class = %@",self.strongString,_strongString,NSStringFromClass([_strongString class]));
    }
    
    //可见copy生成了新的内存空间,而strong没有,修改了原对象值后,strong修饰的属性值也变了。
    str = 123 p = 0x60400044dcb0 &p = 0x7ffeeeb61ee8
    str = 123123 p = 0x60400044dcb0 &p = 0x7ffeeeb61ee8
    copytoString = 123 p = 0xa000000003332313 class = NSTaggedPointerString
    strongString = 123123 p = 0x60400044dcb0 class = __NSCFString
    

    给属性赋值不可变类型值

    - (void)test2
    {
        NSString *str = @"123";
        NSLog(@"str = %@ p = %p &p = %p",str,str,&str);
        self.copytoString = str;
        self.strongString = str;
        
        NSLog(@"copytoString = %@ p = %p class = %@",self.copytoString,_copytoString,NSStringFromClass([_copytoString class]));
        NSLog(@"strongString = %@ p = %p class = %@",self.strongString,_strongString,NSStringFromClass([_strongString class]));
    }
    

    输出结果

    str = 123 p = 0x10eea1078 &p = 0x7ffee0d5dee8
    copytoString = 123 p = 0x10eea1078 class = __NSCFConstantString
    strongString = 123 p = 0x10eea1078 class = __NSCFConstantString
    

    由测试可见,给属性赋于值的对象类型为不可变类型时,Strong和Copy效果一样,浅拷贝,增加引用计数。赋值的对象类型为可变类型时,Strong修饰的属性会浅拷贝,增加引用计数,Copy修饰的属性会深拷贝,不增加引用计数。

    4. 相关知识:深拷贝,浅拷贝

    浅拷贝 浅拷贝就是复制指向对象的指针。
    retain、strong、不可变对象的copy都属于浅拷贝。

    深拷贝 深拷贝就是拷贝对象本身。
    可变对象的copy 和mutableCopy 是深拷贝。

    而weak和unsafe_unretain应该也属于浅拷贝,不过不增加引用计数。最后这个是自己猜的。

    相关文章

      网友评论

          本文标题:iOS内存管理:属性修饰符Strong和Copy

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