美文网首页基础知识
OC中用strong修饰的NSString什么情况下才会改变

OC中用strong修饰的NSString什么情况下才会改变

作者: QYiZHong | 来源:发表于2019-03-06 16:06 被阅读3次

    前言

    昨天跟人争论了一个问题:
    两个使用strong修饰的NSString对象str1和str2,给str1赋值为@"123"然后再把str1赋给str2,然后此时再去改变str1。操作如下:

    @property (nonatomic, strong) NSString *str1;
    @property (nonatomic, strong) NSString *str2;
    
    self.str1 = @"123";
    self.str2 = self.str1;
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    self.str1 = @"321";
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    

    我之前的结论是只要他们都是strong修饰的,改了str1那么str2也会变。争论很激烈,然后我发现我错了...

    结论是这样的

    str1: 123, str2: 123
    str1: 0x10471e060, str2: 0x10471e060
    str1: 321, str2: 123
    str1: 0x10471e0c0, str2: 0x10471e060
    

    一开始他们确实是指向同一块内存地址,但是重新给str1赋值完,即使它是strong修饰的,它也变了一个新地址。

    所以我现在有一个疑问,到底什么时候用strong修饰NSString才会改变?

    验证

    第一种,让str1为NSMutableString类型,通过赋值改变str1

    @property (nonatomic, strong) NSMutableString *str1;
    @property (nonatomic, strong) NSString *str2;
    
    self.str1 = @"123".mutableCopy;
    self.str2 = self.str1;
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    self.str1 = @"321".mutableCopy;
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    

    结论是直接通过赋值改变str1,str2仍然不会变。我对此的理解是赋值@"321".mutableCopy给str1,使得str1又指向了另一块内存地址,所以不会改变str2

    str1: 123, str2: 123
    str1: 0x10471e060, str2: 0x10471e060
    str1: 321, str2: 123
    str1: 0x10471e0c0, str2: 0x10471e060
    

    第二种,让str1为NSMutableString类型,通过方法改变str1

    @property (nonatomic, strong) NSMutableString *str1;
    @property (nonatomic, strong) NSString *str2;
    
    self.str1 = @"123".mutableCopy;
    self.str2 = self.str1;
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    [self.str1 appendString:@"321"];
    NSLog(@"str1: %@, str2: %@", self.str1, self.str2);
    NSLog(@"str1: %p, str2: %p", self.str1, self.str2);
    

    结论是str2随着str1改变了,我对此的理解是str1和str2都指向同一快内存地址,这个时候通过append去改变str1并不会给str1换一个内存地址,所以str2就随着str1改变了。

    str1: 123, str2: 123
    str1: 0x600000dd0ab0, str2: 0x600000dd0ab0
    str1: 123321, str2: 123321
    str1: 0x600000dd0ab0, str2: 0x600000dd0ab0
    

    所以NSString的属性使用copy修饰的目的就在于预防这种情况。同理,其他的容器类对象也是一样的,比如说NSArray也要用copy去修饰。

    最后

    写在最后,我们应该去思考一下有没有一种别的办法让strong修饰的NSString类型不会随着NSMutableString对象的改变而改变。结论肯定是有的,那就是在把str1赋给str2时.copy一下做一次深拷贝。

    self.str2 = self.str1.copy;
    

    这样str2即使是strong修饰,也会因为与str1所指向的内存地址不同而不会随之改变。当然个人建议还是要遵守使用copy进行修饰,而且在手动把可变类型赋值给不可变类型是就顺手.copy一下。这样做的原因是你可能下意识会觉得一个NSString的属性会是copy修饰,但是你不能保证实际中的代码一定是这样。因为写代码难免会出现疏忽,可变类型赋值给不可变类型中copy一下只是增加了一点点损耗但是却能保证在这里赋值绝对不会出bug,这个价值是值得我们去这么做的。

    相关文章

      网友评论

        本文标题:OC中用strong修饰的NSString什么情况下才会改变

        本文链接:https://www.haomeiwen.com/subject/coqxpqtx.html