NSSting 類族
NSSting 是一個類族(Class Clusters),最后生成的對象類型,取決于我們調(diào)用的初始化方法(Toll-free bridgin橋接機(jī)制 來實現(xiàn))
Toll-free bridgin橋接機(jī)制
Toll-free bridging,簡稱為TFB,是一種允許某些ObjC類與其對應(yīng)的CoreFoundation類(Core Foundation框架 (CoreFoundation.framework) 是一組C語言接口,它們?yōu)閕OS應(yīng)用程序提供基本數(shù)據(jù)管理和服務(wù)功能)之間可以互換使用的機(jī)制。比如 NSString與CFString是橋接(bridged)的, 這意味著可以將任意NSString當(dāng)做CFString使用,也可以將任意的CFString當(dāng)做NSString使用。
原理(拿NSString舉例)大概是:NSString是一個抽象類,每當(dāng)你創(chuàng)建一個NSString實例,實際上是創(chuàng)建的NSString的一個私有子類實例。其中一個私有子類就是NSCFString,其是CFString類的在ObjC中的對應(yīng)類。NSCFString實現(xiàn)了作為NSString需要的所有方法。
我的理解:總之,你知道有Toll-Free Bridging橋接機(jī)制,然后NSCFString是NSString的私有子類,實現(xiàn)了它的所有方法。

NSSting 類型:
NSCFConstantString:常量類型,保存在常量區(qū),有時候也在棧區(qū),引用計數(shù)同樣為-1
NSCFString:堆區(qū), 引用計數(shù)同樣為 1
NSTaggedPointerString:優(yōu)化的NSCFString,引用計數(shù)同樣為-1
NSTaggedPointerString (0-9位是taggedpointer類型)
對于64位程序,為了節(jié)省內(nèi)存和提高運行速度,蘋果引入了 Tagged Point 技術(shù)。
NSTaggedPointerString是對NSCFString優(yōu)化后的存在,在運行時創(chuàng)建時對字符串的內(nèi)容和長度做出判斷,若字符串內(nèi)容是由ASCII字符構(gòu)成且長度較?。ù蟾攀畟€字符以內(nèi)),這時候創(chuàng)建的字符串就是NSTaggedPointerString類型,字符串直接存儲在指針里,引用計數(shù)同樣為-1,不適用對象的內(nèi)存管理策略。
//類型=__NSCFConstantString, 地址=0x101d1a098
static NSString *a = @"a";
- (void)test {
//類型=__NSCFConstantString, 地址=0x101d1a0d8
NSString *a0 = @"aaa";
NSString *a1 = [[NSString alloc] init];
a0 = @"a0";
NSString *a2 = [[NSString alloc] initWithString:a0];
//類型=NSTaggedPointerString, 地址=0x89a6aa09cd52cc1f
NSString *a3 = [NSString stringWithFormat:@"%s", "str2"];
NSString *a4 = [NSString stringWithFormat:@"%d", 123];
NSString *a5 = [NSString stringWithFormat:@"%d", YES];
//類型=__NSCFString, 地址=0x60000032a5a0
NSString *a6 = [[NSString alloc] initWithFormat:@"aaa"];
//類型=__NSCFString, 地址=0x60000032a520,
NSString *a7 = [NSString stringWithFormat:@"%@", @"aaa"];
//類型=NSTaggedPointerString, 地址=0x89a6aa09cd52cc1f
NSString *a8 = [NSString stringWithFormat:@"%@", a3];
//類型=__NSCFString, 地址=0x600000d70de0
NSMutableString *a9 = [NSMutableString stringWithFormat:@"%@", a0];
NSMutableString *a10 = [NSMutableString stringWithFormat:@"%@", a3];
NSMutableString *a11 = [NSMutableString stringWithFormat:@"%@", a6];
}
結(jié)論:
- 普通創(chuàng)建的字符串和
static字符串都是NSCFConstantString類型,如:a0 ~ a2。- 使用
initWithFormat方法創(chuàng)建,參數(shù)為基礎(chǔ)數(shù)據(jù)類型(如:char、bool、int等等)或NSTaggedPointerString類型, 字符串都是NSTaggedPointerString類型,如:a3~a5,a8。- 使用
initWithFormat方法創(chuàng)建,參數(shù)為對象類型的,字符串是NSCFString類型。如 a6~a7 和 a9 ~ a11
Tagged Pointer
Tagged Pointer專門用來存儲小的對象,例如NSNumber和NSDate
Tagged Pointer指針地址保存的其實是(對象地址+值)。所以,實際上它不再是一個對象了,它只是一個披著對象皮的普通變量而已。所以,它的內(nèi)存并不存儲在堆中,也不需要malloc和free。
在內(nèi)存讀取上有著3倍的效率,創(chuàng)建時比以前快106倍。
由此看來,NSTaggedPointerString根本不是對象,是分配在棧區(qū)的
copy and mutableCopy
@property (nonatomic, strong) NSString *str;
@property (nonatomic, strong) NSString *str1;
@property (nonatomic, copy) NSString *str2;
@property (nonatomic, copy) NSString *str3;
- (void)test {
//類型=__NSCFConstantString, 地址=0x10ca08098
self.str = @"aaa";
self.str1 = self.str;
//str 類型=__NSCFConstantString, 地址=0x10ca08098
//str1 類型=__NSCFConstantString, 地址=0x10ca08138
self.str1 = @"bbb";
//類型=__NSCFConstantString, 地址=0x10ca08158
self.str2 = @"ccc";
self.str3 = self.str2;
//類型=__NSCFConstantString, 地址=0x10ca08158
//類型=__NSCFConstantString, 地址=0x10ca081b8
self.str3 = @"ddd";
}
- (void)test1 {
//類型=__NSCFConstantString, 地址=0x10ca08098
self.str = @"aaa";
self.str1 = [self.str copy];
//str 類型=__NSCFConstantString, 地址=0x10ca08098
//str1 類型=__NSCFConstantString, 地址=0x10ca08138
self.str1 = @"bbb";
//類型=__NSCFConstantString, 地址=0x10ca08158
self.str2 = @"ccc";
self.str3 = [self.str2 copy];
//類型=__NSCFConstantString, 地址=0x10ca08158
//類型=__NSCFConstantString, 地址=0x10ca081b8
self.str3 = @"ddd";
}
- (void)test2 {
//類型=__NSCFConstantString, 地址=0x10ca08098
self.str = @"aaa";
//類型=__NSCFString, 地址=0x600003a60e70
self.str1 = [self.str mutableCopy];
//str 類型=__NSCFConstantString, 地址=0x10ca08098
//str1 類型=__NSCFConstantString, 地址=0x10b926138
self.str1 = @"bbb";
//類型=__NSCFConstantString, 地址=0x10ca08158
self.str2 = @"ccc";
//類型= NSTaggedPointerString, 地址=0xaec7592a59dc294c
self.str3 = [self.str2 mutableCopy];
//類型=__NSCFConstantString, 地址=0x10ca08158
//類型=__NSCFConstantString, 地址=0x10b9261b8
self.str3 = @"ddd";
}
總結(jié):
- 不管是
strong還是copy修飾字符串屬性,使用=賦值 和copy都會出現(xiàn) swift 的寫時復(fù)制的效果(而原來學(xué)習(xí)的時候,這2個關(guān)鍵字是深拷貝和淺拷貝的區(qū)別,估計是系統(tǒng)在新版本給做了優(yōu)化)。- 使用
mutableCopy全部按照深拷貝去實現(xiàn)。- 如果是局部變量,呈現(xiàn)的效果和屬性是一樣的。