iOS 刷新对 NSString 字符串 的认知
2020-12-15 本文已影响0人
BlackStar暗星
首先字符串其实是有很多种类型的,如
__NSCFConstantString
__NSCFString
NSTaggedPointerString
初始化字符串的几个方法:
//__NSCFConstantString ,内存在数据区
NSString * str = @"hello world";
// __NSCFString类型,内存在堆区,autorelease 型
NSString * str = [NSString stringWithFormat:@"nicknicknick"];
// NSTaggedPointerString类型,内存在栈区
NSString * str = [NSString stringWithFormat:@"nick"];
// __NSCFString类型,内存在堆区
NSString * str = [[NSString alloc]initWithFormat:@"nicknicknick"];
// NSTaggedPointerString类型,内存在栈区
NSString * str = [[NSString alloc]initWithFormat:@"nick"];
说明
对于 stringWithFormat 和 [[NSString alloc]initWithFormat] 而言,如果初始化的 ‘字符串’ 长度不超过 11 位,(位数不确定,我这个例子是11位,必须是字母,汉字不可以 )那么类型就是
NSTaggedPointerString
否则是__NSCFString
,如果使用NSString *xxx = @"xxx"
直接赋值 ,那么不管长度多少,类型都是__NSCFConstantString
注释:对于字符串多长才改变字符串类型,这个是不固定的,但是具体的规则我没弄清楚,比如说aaaaaaaa12 ,虽然只有10位,但是他是__NSCFString类型,具体怎么改变。猜测:可能跟存储有关,因为TaggedPoint是将值存在了指针里,如果指针占用的内存不够存储其值了,就会改变
验证
WechatIMG18065.pngWeChat2af3825cde63f53ea222f96da1da3052.png
关于字符串判等和地址的问题
首先要知道,==
是对地址的比较
// 情况一
NSString * firstName = [[NSString alloc]initWithFormat:@"nicknicknicknick"];
NSString * secondName = [[NSString alloc]initWithFormat:@"nicknicknicknick"];
if (firstName == secondName) {
NSLog(@"相等:%p == %p",firstName,secondName);
}else{
NSLog(@"不相等:%p == %p",firstName,secondName);
}
//地址不相等
打印:不相等:0x6000021ee670 == 0x6000021ee550
// 情况二 ----------------------------------------------------------------
NSString * firstName = [[NSString alloc]initWithFormat:@"nick"];
NSString * secondName = [[NSString alloc]initWithFormat:@"nick"];
// 地址相等
打印:相等:0xde6fb5b6280d4ec0 == 0xde6fb5b6280d4ec0
// 情况三 ----------------------------------------------------------------
NSString * firstName = @"nick";
NSString * secondName = @"nick";
// 地址相等
打印:相等:0x10918fa88 == 0x10918fa88
总结
系统对字符串是有优化的,如果是在 数据区或者栈区 的 字符串,对于值相同的字符串,会使用同一份内存地址,也就是一个字符串对象,在判等的时候,就会相等,如果是在堆区,也就是我们自己管理内存,才会使用新的内存地址去存储新的对象,所以即便 字符串的 value 相同,但是也不是同一个对象。