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

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)