NSString属性为什么要用copy修饰

字数 321阅读 217

Property-NSString-Copy

NSString 属性为什么应该使用copy修饰,使用strong为什么不行?在之前一直都知道NSString/Blocks类型的属性应该使用copy来修饰,一直没研究过到底为什么?前几天看到一篇blog感觉讲得较完善,那么我也把自己的一点体会和理解记录下吧,欢迎指正。

  • 我们先定义一个测试类BMPerson
@interface BMPerson : NSObject
@property (strong, nonatomic) NSString *strStrong; ///< strStrong
@property (copy, nonatomic) NSString *strCopy; ///< strCopy
@property (strong, nonatomic) NSObject *obj; ///< obj
@end

@implementation BMPerson
- (void)logFunc {
    NSLog(@"_strStrong的内容: %@  _strStrong 存放的地址:%p _strStrong 的地址:%p", _strStrong, _strStrong, &_strStrong);
    NSLog(@"_strCopy的内容: %@  _strCopy 存放的地址:%p _strCopy 的地址:%p", _strCopy, _strCopy, &_strCopy);
}
@end
  • main函数中执行如下代码:
NSString *str = @"abc";
BMPerson *per = [BMPerson new];
per.strStrong = str;
per.strCopy = str;
NSLog(@"str修改前: str的内容: %@  str 存放的地址:%p str 的地址:%p", str, str, &str);
[per logFunc];
NSLog(@"\n");
str = @"qwe";
NSLog(@"str修改后: str的内容: %@  str 存放的地址:%p str 的地址:%p", str, str, &str);
[per logFunc];

会输出如下的log

035304+0800 Demo[58039:7367327] str修改前: str的内容: abc  str 存放的地址:0x100002098 str 的地址:0x7fff5fbff748
035455+0800 Demo[58039:7367327] _strStrong的内容: abc  _strStrong 存放的地址:0x100002098 _strStrong 的地址:0x100200198
035483+0800 Demo[58039:7367327] _strCopy的内容: abc  _strCopy 存放的地址:0x100002098 _strCopy 的地址:0x1002001a0
035503+0800 Demo[58039:7367327] 
035513+0800 Demo[58039:7367327] str修改后: str的内容: qwe  str 存放的地址:0x1000020f8 str 的地址:0x7fff5fbff748
035522+0800 Demo[58039:7367327] _strStrong的内容: abc  _strStrong 存放的地址:0x100002098 _strStrong 的地址:0x100200198
035543+0800 Demo[58039:7367327] _strCopy的内容: abc  _strCopy 存放的地址:0x100002098 _strCopy 的地址:0x1002001a0
  • 似乎是strongcopy没有任何区别,那么我们换一种方式看看。
NSMutableString *str = [NSMutableString stringWithFormat:@"abc"];
BMPerson *per = [BMPerson new];
per.strStrong = str;
per.strCopy = str;
NSLog(@"str修改前: str的内容: %@  str 存放的地址:%p str 的地址:%p", str, str, &str);
[per logFunc];
NSLog(@"\n");
[str appendString:@"+a"];
NSLog(@"str修改后: str的内容: %@  str 存放的地址:%p str 的地址:%p", str, str, &str);
[per logFunc];

会输出如下的log

035625+0800 Demo[58039:7367327] str修改前: str的内容: abc  str 存放的地址:0x100200a80 str 的地址:0x7fff5fbff738
035735+0800 Demo[58039:7367327] _strStrong的内容: abc  _strStrong 存放的地址:0x100200a80 _strStrong 的地址:0x100200198
035755+0800 Demo[58039:7367327] _strCopy的内容: abc  _strCopy 存放的地址:0x63626135 _strCopy 的地址:0x1002001a0
035760+0800 Demo[58039:7367327] 
035770+0800 Demo[58039:7367327] str修改后: str的内容: abc+a  str 存放的地址:0x100200a80 str 的地址:0x7fff5fbff738
035778+0800 Demo[58039:7367327] _strStrong的内容: abc+a  _strStrong 存放的地址:0x100200a80 _strStrong 的地址:0x100200198
035794+0800 Demo[58039:7367327] _strCopy的内容: abc  _strCopy 存放的地址:0x63626135 _strCopy 的地址:0x1002001a0

我们发现本来给 per.strStrong 赋值的是 @“abc”,但在修改了str后发现per.strStrong的值也变了,但是使用copy修饰的并不会变化,那么到底是什么问题呢?我在blog的基础上简单画了下内存分配图如下:

  • 第一种方式


  • 第二种方式


  • 由上面的图我相信可以清楚发现问题的所在了,使用我们声明NSSring声明的属性时尽量使用copy吧。

Demo地址

Demo地址 https://github.com/asiosldh/Property-NSString-Copy

参考

推荐阅读更多精彩内容