前言
当被学长问到NSString的三种实现形式时,大脑是空白的。
通过学习学长们的博客,查阅资料,悔不当初没有好好学习。
现在,让我们来探索一下OC中NSString的三种形式吧~
NSString三种类型的出现
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *a = @"hello";
NSString *b = @"hello,iOS!";
NSString *c = [NSString stringWithFormat:@"hello"];
NSString *d = [NSString stringWithFormat:@"hello,iOS!"];
NSString *e = [NSString stringWithFormat:@"嗨"];
NSLog(@"%p %@ \n %p %@ \n%p %@\n %p %@ \n%p %@", a, [a class], b, [b class] , c, [c class], d, [d class], e, [e class]);
}
return 0;
}
运行上述代码,我们会发现同样是NSString类型,但是有三种不同的类型
__NSCFConstantString
该类型正如其名字,是一种Constant常量型字符串。创建方式即是@""直接创建,储存在字符串常量区中。
NSString *a = @"hello";
NSString *b = @"hello,iOS!";
NSString *c3 = [NSString stringWithString:@"hello"];
该类型有如下特点:
- 作为常量字符串,是一种编译时常量
- 储存在字符串常量区
- retainCount的值非常大,无法被释放
- 使用不同的字符串对象进行创建时,只要内容相同,则对象的地址也相同。
NSString *c1 = @"hello";
NSString *c2 = @"hello";
NSString *c3 = [NSString stringWithString:@"hello"];
NSLog(@"c1: %p %@ \nc2: %p %@\nc3: %p %@", c1, [c1 class], c2, [c2 class], c3, [c3 class]);
运行结果如下所示:
__NSCFString
该类型与__NSCFConstantString不同,是在运行时创建的NSString子类,并不是字符串常量类型,在被创建时获得了1的引用计数,因此是可以被释放的。该类型有如下特点:
- 运行时创建,储存在堆上。因此使用相同的内容创建字符串对象时,字符串对象的地址也不相同。
- 使用stringWithFormat的类方法创建该对象时,一般都是__NSCFString类。
- 当字符串长度大于9时,以该类储存,但如果小于9,则会变成NSTaggedPointerString类。
- 如果字符串对象的内容是中文,则无论长短,都是__NSCFString类。
该类型的创建需要使用stringWithFormat类方法(注意,使用stringWithString的实例方法创建的是__NSCFConstantString类):
NSString *d = [NSString stringWithFormat:@"hello,iOS!"];
NSString *e = [NSString stringWithFormat:@"嗨"];
NSTaggedPointerString
学习这一类型,我们首先要认识标签指针的概念,这里转载一下学长博客的内容。
对于NSTaggedPointerString类型,有如下特点:
- 引用计数很大,是一个无法释放的单例常量对象,使用不同的字符串对象进行创建时当内容相同时,字符串对象的地址也相同,但是是在运行时创建
- 使用stringWithForma类方法创建字符串对象时,当非字面值常量的数字,英文字母字符串的长度小于等于9(来源于学长博客的数据)时,会自动成为NSTaggedPointerString类。
我们以下面这段代码来探究该类:
NSString *t1 = [NSString stringWithFormat:@"loveiOS"];
NSString *t2 = [NSString stringWithFormat:@"哈"];
NSString *t3 = [NSString stringWithFormat:@"doyoulikeiOS"];
NSLog(@"t1: %p %@ \nt2: %p %@\nt3: %p %@", t1, [t1 class], t2, [t2 class], t3, [t3 class]);
这是结果:
总结
__NSCFString:在运行时创建的一种 NSString 子类,被储存在堆区即动态区。
感谢学长学姐们为我们学习带来的便利,往后要更加提高学习的主动性,多探索,多学习,多实践。