NSString

作者: 今天写明天改 | 来源:发表于2021-05-03 15:40 被阅读0次

背景

NSString 大家都不陌生了,但是用起来的时候,总是有点不清楚

今天主要和大家说下NSString的修饰符问题

首先,我们知道NSString 可以用copy修饰,那么,用strong修饰会怎么样, 如果可以,用assign修饰又会怎么样🤔️

基础的属性修饰符strong、copy、assign的区别就不讲了,直接上代码

实验

strong 修饰的NSString

先定义一个属性@property (nonatomic, strong) NSString *name;

然后写测试代码

NSMutableString *oName = [NSMutableString stringWithString:@"hello"];

myClass.name = oName;

oName = [NSMutableString stringWithString:@"world"];

NSLog(@"%@", ocm.name);

当我们执行上边的程序的时候,会发现输出的是hello

如果觉得有点奇怪,我们接着细研究一下

我们在oName = [NSMutableString stringWithString:@"world"];语句前打一个断点

这个时候在控制台查看可以发现两者指向同一个内存地址

p myClass.name

(__NSCFString *) $0 = 0x00006000023fc390 @"hello"

p oName

(__NSCFString *) $1 = 0x00006000023fc390 @"hello"

点击单步调试(一步一步调试更容易理解程序内部发生了什么 --来自老大对我的指导)让程序执行完oName = [NSMutableString stringWithString:@"world"];语句

这个时候我们再来看一下调试器输出

p myClass.name

(__NSCFString *) $2 = 0x00006000023fc390 @"hello"

 p oName

(__NSCFString *) $3 = 0x0000600002335a70 @"world"

发现两者指向了不同的地址,确切的说是oName指向了新的地址。这就是我们所希望的结果,有人可能会有疑问,指向同一个内存的指针,一个变了,另一个内容居然不变?

 但是如果仔细观察上边的输出,可以发现,当oName改变的时候,不是内存区域的值变了,而是,oName的地址变了。这个结论同样适用于属性是NSMutableString的情况和oName是NSString*类型的情况, 至于为什么变,这是后话

copy 修饰的NSString

同样的在oName = [NSMutableString stringWithString:@"world"];语句前打一个断点

p myClass.name

(NSTaggedPointerString *) $0 = 0xf2fe9bc4b2255f98 @"hello"

p oName

(__NSCFString *) $1 = 0x0000600001332610 @"hello"

注意,从赋值之后,两者就处于不同的内存地址中,所以后边的自然也不同了

问题

那么是什么导致了这个现象的发生,NSString的内容修改,字符串指向的地址就要修改吗

首先 导致这个现象的发生,是我在乱使用NSString🧎♂️, 不同于Swift,oc里的String变量有NSString 和NSMutableString

NSSring在官方文档中的解释是

A static, plain-text Unicode string object.

而且,官方也给了提示

An immutable string is a text string that is defined when it is created and subsequently cannot be changed.

所以,当我更改NSString*的值的时候, 例如myClass.name = oName;

本质上,是给原先的指针赋值了一个新的指针,使它指向了新的内存地址。这样才会有上面的错误

而更需要注意的是,当我们仅仅想更改一个字符串的值的时候, 注意 是仅仅想更改值,那么这个时候不应该使用NSString,

要使用NSMutableString

例如将上面的例子修改一下

NSMutableString *oName = [NSMutableString stringWithString:@"hello"];

NSMutableString *changeName=[NSMutableString stringWithString:@"change"];

oName = changeName;

[oNameappendString:@"world"];

当我们在[oNameappendString:@"world"];语句前打一个断点,查看值

p oName

(__NSCFString *) $0 = 0x000060000049b990 @"change"

p changeName

(__NSCFString *) $1 = 0x000060000049b990 @"change"

意料之中,继续单步执行并查看

p oName

(__NSCFString *) $2 = 0x000060000049b990 @"changeworld"

p changeName

(__NSCFString *) $3 = 0x000060000049b990 @"changeworld"

注意到了吗。这两者的地址并没有发生变化,所以,当一个的值发生变化,另一个也跟着变了

总结

所以,希望大家以后使用NSString的时候,分清楚自己要更改的是值,还是要赋值一个新的指针给原指针,如果只需要更改值,那么请使用NSMutableString, 换句话说,如果你可以直接在原地址更改NSString的值,那APPLE的那么多研发人员做NSMutableString是为了什么,一切代码都有它存在的原因。😄

相关文章

网友评论

      本文标题:NSString

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