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应该也属于浅拷贝,不过不增加引用计数。最后这个是自己猜的。