谈谈NSString的copy和strong

CEO Lau的猫

今天在人才孵化基地中,矫总提出了一个问题,然后根据此问题又深入的探索了一番,在此做个总结.

1.先说说用copy修饰

在这里举一个例子

@interface viewController()
@property (nonatomic, copy) NSString *name;//注意这里是用copy修饰的
@end

@implementation viewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableString *str = [NSMutableString stringWithString:@"张三"];
    self.name = str;
    NSLog(@"第一次得到的名字:%@",self.name);
    [str appendString:@"丰"];
    str = nil;
    NSLog(@"第二次得到的名字:%@",self.name);
}

这里打印出来的结果是:

第一次得到的名字:张三
第二次得到的名字:张三

为什么会这样呢? 接下来告诉你
因为NSMutableString是可变字符串,在这里 self.name = str; name是用copy来修饰的,从而进行了一次深拷贝,而当接下来的[str appendString:@"丰"]; str = nil;这些操作也就对self.name没有任何影响了.

那如果换成这样的话,结果会如何?
@interface viewController()
@property (nonatomic, copy) NSString *name;
@end

@implementation viewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableString *str = [NSMutableString stringWithString:@"张三"];
    //把self.name换成了_name
    _name = str;
    NSLog(@"第一次得到的名字:%@",_name);
    [str appendString:@"丰"];
    str = nil;
    NSLog(@"第二次得到的名字:%@",_name);
}

而这次打印出来的结果是:

第一次得到的名字:张三
第二次得到的名字:张三丰

因为使用_name没有去调用生成的set函数,所以copy修饰符不生效,从而进行了一次浅拷贝,而str = nil这个操作为什么没有使得_name为空呢? 因为浅拷贝只是多了一个指向_name的指针,而str = nil把指向str的指向的指针去掉了而已,但仍有一个有效的对象,所以在[str appendString:@"丰"];这一步操作的时候就已经生效了.

2.接下来再说说用strong修饰
@interface viewController()
@property (nonatomic, strong) NSString *name;//注意这里是用strong修饰的
@end

@implementation viewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableString *str = [NSMutableString stringWithString:@"张三"];
    self.name = str;
    [str appendString:@"丰"];
    NSLog(@"得到的名字:%@",self.name);
}

打印出来的结果是:

得到的名字:张三丰

这里要记住 如果使用strong修饰NSString类型属性,self.name 指向可变字符串对象的地址
当可变字符串内容发生变化时,self.name相对应的也发生变化,这次是进行了一次浅拷贝

但是像第一个例子那样,使用copy修饰的话,将可变字符串重新拷贝一份,重新开辟内存空间,修改mutableString的值,不会对self.name造成影响

刚才一直用的是可变字符串NSMutableString,这次用不可变字符串NSString再试试
@interface viewController()
@property (nonatomic, strong) NSString *name;
@end

@implementation viewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *str = [NSString stringWithString:@"张三"];
    self.name = str;
    NSLog(@"第一次得到的名字:%@",self.name);
    str = @"丰";
    NSLog(@"第二次得到的名字:%@",self.name);
}

打印出来的结果是:

第一次得到的名字:张三
第二次得到的名字:张三

将可变字符串变NSMutableString为不可变字符串NSString,在这里的赋值操作self.name = str;,其实是让str重新指向了一片内存空间,并不是修改了str原本内存中的值,所以改变str的指向后,self.name的指向并没有改变,输出没有受到影响。

上面的例子差不多大家都应该明白了,但是有可能在实际操作中,会有一个问题困扰着大家,那就是 NSString到底是用copy还是strong?

在这里将解决你的烦恼:

本质上来讲,copy和strong都没有错,但不是说,NSString用copy就一定是最好的.

那么,什么时候用copy,什么时候用strong呢?

首先,为什么要用copy?

因为copy安全!

copy修饰的NSString,在初始化时,如果来源是NSMutableString的话,会对来源进行一次深拷贝,将来源的内存地址复制一份,这样两个对象就一点关系就没有了,无论你怎么操作来源,都不会对自己的NSString有任何影响
比如:

你有一个@property(nonatomic,copy) NSString *str;
然后有一个NSMutableString *mutableStr;
当你进行str = mutableStr操作之后,紧接着你又改变了mutableStr的内容mutableStr = @"change";
那么str的内容并不会改变. 如果你的str不是copy修饰的,而是strong修饰的,那么str的值也会变成@"change";
因为strong是浅拷贝的,并不会对来源的内存地址进行拷贝
可以结合上面的例子来理解

那么问题来了,既然copy安全,那为什么不都用copy?

这里我们需要了解一点,copy修饰的NSString在进行set操作时,底层是这样实现的:
我们还是举上面那个例子,进行str = mutableStr操作时,内部会执行一个操作:

str = [mutableStr copy];

那么这个copy里面做了什么呢?

if ([str isMemberOfClass:[str class]])

没错,就是进行一次判断,判断来源是可变的还是不可变的,如果是不可变,那么好,接下来的操作就跟strong修饰的没有区别,进行浅拷贝;如果是可变的,那么会进行一次深拷贝

所以,copy操作内部会进行判断,你别小看了这个if操作所消耗的内存,一次不重要,十次可能也可以忽略不计,但当你的项目十分庞大时,有成百上千个个NSString对象,多多少少会对你的app的性能造成一定的影响.

那么回到最初的问题,什么时候用copy,什么时候用strong

你只需要记住一点:

当你给你的NSString对象赋值时,如果来源是NSMutableString,那么这种情况就必须要用copy;如果你确定来源是不可变类型的,比如@"张三丰"这种固定的字符串,那么用strong比较好

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容