iOS基础篇-Copy和Strong

本文仅针对使用字符串、数组、字典时,对copy和Strong展开讨论
1.不可变字符串
申明copy和strong属性字符串

@property (strong, nonatomic) NSString *strStrong; @property (copy, nonatomic) NSString *strCopy;

// 不可变字符串 NSLog(@"不可变字符串:"); NSString *str = @"aaaa"; NSLog(@"str= %@内存地址 = %p 指针地址 = %p",str,str,&str); self.strStrong = str; NSLog(@"strong= %@内存地址 = %p 指针地址 = %p",self.strStrong,self.strStrong,&_strStrong); self.strCopy = str; NSLog(@"copy= %@内存地址 = %p 指针地址 = %p\n",self.strCopy,self.strCopy,&_strCopy);

打印结果
不可变字符串: str= aaaa内存地址 = 0x104ec4098 指针地址 = 0x7ffeead3bbd8 strong= aaaa内存地址 = 0x104ec4098 指针地址 = 0x7fe70100e600 copy= aaaa内存地址 = 0x104ec4098 指针地址 = 0x7fe70100e608

对不可变字符串进行操作:
str = @"bbb"; NSLog(@"对不可变字符串操作后:"); NSLog(@"str= %@内存地址 = %p指针地址 = %p",str,str,&str); NSLog(@"strong= %@内存地址 = %p指针地址 = %p",self.strStrong,self.strStrong,&_strStrong); NSLog(@"copy= %@内存地址 = %p指针地址 = %p\n",self.strCopy,self.strCopy,&_strCopy);

打印结果
对不可变字符串操作后: str= bbb内存地址 = 0x104ec4118指针地址 = 0x7ffeead3bbd8 strong= aaaa内存地址 = 0x104ec4098指针地址 = 0x7fe70100e600 copy= aaaa内存地址 = 0x104ec4098指针地址 = 0x7fe70100e608

结论:源对象为不可变字符串而言,不论使用copy还是strong属性,所对应的值是不发生变化,strong和copy并没有开辟新的内存,即并不是深拷贝。此时,使用copy或是strong,并没有对数据产生影响。 2.可变字符串
// 可变字符串 NSLog(@"可变字符串:"); NSMutableString *mutableStr = [[NSMutableString alloc] initWithString:@"kobe"]; NSLog(@"mutableStr = %@ 内存地址 = %p指针地址 = %p",mutableStr,mutableStr,&mutableStr); self.strStrong = mutableStr; NSLog(@"strong= %@ 内存地址 = %p指针地址 = %p",self.strStrong,self.strStrong,&_strStrong); self.strCopy = mutableStr; NSLog(@"copy= %@ 内存地址 = %p指针地址 = %p\n",self.strCopy,self.strCopy,&_strCopy);

打印结果
可变字符串: mutableStr = kobe 内存地址 = 0x60000005b150指针地址 = 0x7ffeead3bbd0 strong= kobe 内存地址 = 0x60000005b150指针地址 = 0x7fe70100e600 copy= kobe 内存地址 = 0xa00000065626f6b4指针地址 = 0x7fe70100e608

对可变字符串进行操作:
NSLog(@"对可变字符串操作后:"); [mutableStr appendString:@"-bryant"]; NSLog(@"mutableStr = %@ 内存地址 = %p指针地址 = %p",mutableStr,mutableStr,&mutableStr); NSLog(@"strong= %@ 内存地址 = %p指针地址 = %p",self.strStrong,self.strStrong,&_strStrong); NSLog(@"copy= %@ 内存地址 = %p指针地址 = %p",self.strCopy,self.strCopy,&_strCopy);

打印结果
对可变字符串操作后: mutableStr = kobe-bryant 内存地址 = 0x60000005b150指针地址 = 0x7ffeead3bbd0 strong= kobe-bryant 内存地址 = 0x60000005b150指针地址 = 0x7fe70100e600 copy= kobe 内存地址 = 0xa00000065626f6b4指针地址 = 0x7fe70100e608

结论:数据源为可变字符串而言,使用copy申明属性,会开辟一块新的内存空间存放值,源数据不论怎么变化,都不会影响copy属性中的值,属于深拷贝;使用strong申明属性,不会开辟新的内存空间,只会引用到源数据内存地址,因此源数据改变,则strong属性也会改变,属于浅拷贝。 在实际开发中,我们不希望源数据改变影响到属性中的值,故而使用copy来申明。
3.属性为可变数组、可变字典
例如:当我们使用copy修饰NSMutableArray时
@property (copy, nonatomic) NSMutableArray *originArray; self.originArray = [NSMutableArray arrayWithCapacity:0]; NSLog(@"self. originArray class name %@",[self.originArray class]); 打印结果:self. originArray class name __NSArrayI

【iOS基础篇-Copy和Strong】我们可以看到,copy申明的可变数据,初始化或复值之后,变成不可变数组,对数组执行增,删会跑出错误。这是因为copy属性修饰后,在初始化或赋值时,会先执行copy操作,然后赋值。
结论:在实际开发中,我们需要对可变数组、字典使用strong属性修饰。

    推荐阅读