iOS NSString的内存情况

在iOS 的内存管理里面,NSString算是一个比较特殊的情况,它是一个OC对象,可是它的内存管理跟它指向的内容有关。

主要分两种:

(1)NSString 指向一个常量字符串,即在编译时已经确定的值,那么NSString就不受内存管理

(2)除开第一种情况,那么NSString就跟其他OC对象一样,受retainCount控制。

 测试代码

NSString *str11 = @"dsfsdfdddd";
NSString *str22 = [NSString stringWithFormat:@"dsfdsfds"];
NSString *str33 = [NSString stringWithString:str22];
NSLog(@"str11:%lu --- str22:%lu --- str33:%lu", [str11 retainCount], [str22 retainCount], [str33 retainCount]);

输出:

str11:18446744073709551615 --- str22:18446744073709551615 --- str33:1

那么试着输出在lldb这几个对象输出这几个对象的class

(lldb) po str11.class

__NSCFConstantString


(lldb) po str22.class

NSTaggedPointerString


(lldb) po str33.class

__NSCFString


第一个str11是一个常量字符串__NSCFConstantString,他指向一个常量,可以这样理解,编译器在编译的时候,把这个变量值@"dsfsdfdddd"添加到常量表里面,常量表里面的变量在APP结束之后才会被释放,指向这块常量表的指针都不受retainCount管理(或者这样理解:所有指向常量的变量在编译时都被替换成常量地址,那么就不存在OC指针的内存释放了)

第二个str22比较特殊,如果stringWithFormat里面直接写一个字符串,那么编译器会编译成一个字符串常量,那么跟第一种情况是一样的(可能个人理解有偏差)。

如果stringWithFormat需要进行拼接,那么stringWithFormat会返回一个mutableString类型

测试代码:把上面str22的代码换成这个

NSString *str22 = [NSString stringWithFormat:@"dsfdsfds%i", 11];

 
  

输出:__NSCFString ,retainCount==1

并且可以在调试时候看到str22类型是NSMutableString

第三个str33跟str22类似,如果stringWithString参数是个字符串对象,如stringWithString:str22,那么函数返回结果是一个NSMutableString对象;而如果是指定一个字符串值,如stringWithString:@"dsadsa",那么返回的就是一个__NSCFConstantString,这里应该是编译器在编译时自行优化了

NSString *str33 = [NSString stringWithString:@"dsadsa"];

替换成:

NSString *str33 = @"dsadsa";

那就和第一个str11一样的了


另外retain/copy操作对常量字符串无效

比如NSString *str11 = [@"dddd" copy];

str11不会变化,个人理解在 copyWithZone里面,系统会判断对象是不是指向常量。

你可能感兴趣的:(iOS内存)