iOS 关键字 copy 与 strong

今天说一下ios的修饰关键字copy与strong在使用时的区别

对可变对象NSMutableString

@property (strong, nonatomic) NSMutableString *retainMstr;
@property (copy, nonatomic) NSMutableString *mStr;
    NSMutableString *mutableStr = [NSMutableString stringWithString:@"hello"];
    self.retainMstr = mutableStr;
    self.mStr = mutableStr;
    
    NSLog(@"原    : %@  %p:",mutableStr,mutableStr);
    NSLog(@"strong: %@  %p:",self.retainMstr,self.retainMstr);
    NSLog(@"copy  : %@  %p:",self.mStr,self.mStr);

打印输出

2020-02-16 19:56:01.890207+0800 iosDemo1[19551:1823733] 原    : hello  0x600003776c10:
2020-02-16 19:56:01.890372+0800 iosDemo1[19551:1823733] strong: hello  0x600003776c10:
2020-02-16 19:56:01.890522+0800 iosDemo1[19551:1823733] copy  : hello  0xf146d5c1dcf28cc0:

结论

可以看出,对可变对象:
strong修饰,赋值时只是拷贝了指针,没有开辟新内存.
而copy修饰,赋值时开辟了新内存.

我们可以大胆猜测,如果修改了原数据,那么就会影响strong修饰的对象,而不会影响copy修饰的对象

开始修改操作

[mutableStr appendString:@" world"];
    
NSLog(@"原    : %@  %p:",mutableStr,mutableStr);
NSLog(@"strong: %@  %p:",self.retainMstr,self.retainMstr);
NSLog(@"copy  : %@  %p:",self.mStr,self.mStr);

打印输出

2020-02-16 19:56:01.890628+0800 iosDemo1[19551:1823733] 原    : hello world  0x600003776c10:
2020-02-16 19:56:01.890700+0800 iosDemo1[19551:1823733] strong: hello world  0x600003776c10:
2020-02-16 19:56:01.890788+0800 iosDemo1[19551:1823733] copy  : hello  0xf146d5c1dcf28cc0:

测试结果表明我们的猜测是正确的.

重点!!!

如果赋值的数据是可变对象,如果不希望受到它的修改而影响,那就用copy修饰.

对不可变对象NSString

@property (strong, nonatomic) NSString *str_strong;
@property (copy, nonatomic) NSString *str_copy;
NSString *str1 = @"123";
self.str_strong = str1;
self.str_copy = str1;
    
NSLog(@"原    : %@  %p:",str1,str1);
NSLog(@"strong: %@  %p:",self.str_strong,self.str_strong);
NSLog(@"copy  : %@  %p:",self.str_copy,self.str_copy);
    
str1 = @"456";
    
NSLog(@"原    : %@  %p:",str1,str1);
NSLog(@"strong: %@  %p:",self.str_strong,self.str_strong);
NSLog(@"copy  : %@  %p:",self.str_copy,self.str_copy);
   

打印输出

2020-02-16 20:07:06.074246+0800 iosDemo1[19703:1863001] 原    : 123  0x108a0c040:
2020-02-16 20:07:06.074367+0800 iosDemo1[19703:1863001] strong: 123  0x108a0c040:
2020-02-16 20:07:06.074447+0800 iosDemo1[19703:1863001] copy  : 123  0x108a0c040:
2020-02-16 20:07:06.074536+0800 iosDemo1[19703:1863001] 原    : 456  0x108a0c0c0:
2020-02-16 20:07:06.074610+0800 iosDemo1[19703:1863001] strong: 123  0x108a0c040:
2020-02-16 20:07:06.074684+0800 iosDemo1[19703:1863001] copy  : 123  0x108a0c040:

结论

可以看出,对于不可变字符串:
strong修饰和copy修饰,都是浅拷贝,指针复制,并没有开辟新的内存空间.

这个时候,可能有人要说了:既然是浅拷贝,那修改源数据应该会影响它们啊.然而事实并没有产生影响.
因为对不可变字符串重新赋值时,系统又为其分配了新的内存空间.str1的指针变了,指向了新的内存空间. 但是copy和strong的指针没有改变.指向的依然是原来str1指向的那块内存.


对可变对象NSMutableArray

@property (strong, nonatomic) NSMutableArray *strong_Array;
@property (copy, nonatomic) NSMutableArray *copyy_Array;
   NSMutableArray *mArr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
    self.strong_Array = mArr;
    self.copyy_Array = mArr;
    
    NSLog(@"原    : %@  %p:",mArr,mArr);
    NSLog(@"strong: %@  %p:",self.strong_Array,self.strong_Array);
    NSLog(@"copy  : %@  %p:",self.copyy_Array,self.copyy_Array);
    
    [self.strong_Array addObject:@"3"];
    NSLog(@"修改strong对象后----------------");

    NSLog(@"原    : %@  %p:",mArr,mArr);
    NSLog(@"strong: %@  %p:",self.strong_Array,self.strong_Array);
    NSLog(@"copy  : %@  %p:",self.copyy_Array,self.copyy_Array);

    [self.copyy_Array addObject:@"4"];

打印输出

2020-02-16 20:27:35.401768+0800 iosDemo1[19956:1932798] 原    : (
    1,
    2
)  0x6000036e2a60:
2020-02-16 20:27:35.401909+0800 iosDemo1[19956:1932798] strong: (
    1,
    2
)  0x6000036e2a60:
2020-02-16 20:27:35.402002+0800 iosDemo1[19956:1932798] copy  : (
    1,
    2
)  0x6000038f6160:
2020-02-16 20:27:35.402076+0800 iosDemo1[19956:1932798] 修改strong对象后----------------
2020-02-16 20:27:35.402172+0800 iosDemo1[19956:1932798] 原    : (
    1,
    2,
    3
)  0x6000036e2a60:
2020-02-16 20:27:35.402256+0800 iosDemo1[19956:1932798] strong: (
    1,
    2,
    3
)  0x6000036e2a60:
2020-02-16 20:27:35.402338+0800 iosDemo1[19956:1932798] copy  : (
    1,
    2
)  0x6000038f6160:
2020-02-16 20:27:35.402449+0800 iosDemo1[19956:1932798] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x6000038f6160
(lldb) 

可以看出:
修改strong对象后,会影响源数据,当然修改源数据也会影响strong修饰的对象.而不会影响copy修饰的对象.因为copy开辟新内存了.
而对copy进行修改的时候直接crash. 因为copy返回的是不可变对象.

结论

对于可变容器类对象(NSMutableArray,NSMutableDictionary,NSMutableSet...)
要用strong修饰

大总结:

对于不可变对象:strong和copy修饰,都是浅拷贝, 当对源数据修改时并无影响,用哪个都可以.
对于可变对象:strong浅拷贝,copy深拷贝.
如果不希望数据收到源数据的修改而影响就用copy.反之用strong
对可变对象修饰:一定要用strong. 因为copy返回的是不可变对象.

如有错误,欢迎指正!

你可能感兴趣的:(iOS 关键字 copy 与 strong)