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

我们可以看到,copy申明的可变数据,初始化或复值之后,变成不可变数组,对数组执行增,删会跑出错误。这是因为copy属性修饰后,在初始化或赋值时,会先执行copy操作,然后赋值。

结论:在实际开发中,我们需要对可变数组、字典使用strong属性修饰。

你可能感兴趣的:(iOS基础篇-Copy和Strong)