NSString 和 NSMutableString 的區(qū)別

在 Objective-C 的編程中,NSString 是使用率非常高的一個(gè)類,用法也很簡(jiǎn)單。

NSString 表示一個(gè)固定字符串,關(guān)鍵點(diǎn)就在于固定二字。當(dāng)你給一個(gè) NSString 變量賦值之后,字符串本身是不能再改變的。

NSString * name = @"張三";

name = @"李四";

你可以發(fā)現(xiàn),以上代碼執(zhí)行并不會(huì)出錯(cuò),并不是說(shuō)固定字符串這種說(shuō)法是錯(cuò)的。先分析一下,其實(shí)你把李四賦值給name,只是改變了name變量的指針,而不是張三本身。保存張三的內(nèi)存還是靜靜地躺在那里,一動(dòng)也不動(dòng)。

繼續(xù)執(zhí)行代碼

name = @"王五";

這樣其實(shí)內(nèi)存里面有三塊內(nèi)存,分別存儲(chǔ) 張三、李四、王五。

比如說(shuō)張三內(nèi)存是 0x001,李四內(nèi)存 0x002,王五內(nèi)存0x003,那么看下以下代碼的執(zhí)行結(jié)果

NSString * name = @"張三";  // name 指向內(nèi)存 0x001
name = @"李四";// name 指向內(nèi)存 0x002
name = @"王五";// name 指向內(nèi)存 0x003

name = @"張三";// name 重新指向內(nèi)存 0x001
name = @"王五";// name 重新指向內(nèi)存 0x003

一般來(lái)說(shuō),如果在源代碼里面出現(xiàn)的字符串會(huì)被編譯器保存在二進(jìn)制文件的text段,在二進(jìn)制加載到內(nèi)存的時(shí)候就存在了,不會(huì)臨時(shí)分配所需內(nèi)存。

不可變字符串有很多好處,最重要的一個(gè)就是多線程安全,因?yàn)椴豢勺?,所以任何線程都可以隨意使用它。在程序編寫中,如果沒(méi)有特殊需求,一般都是使用NSString保存字符串。

當(dāng)然你會(huì)有特殊需求,比如你現(xiàn)在正在處理一批用戶輸入,代碼如下

NSString * input = @"";
        
input = [input stringByAppendingString:@"input text1\t"];
                
input = [input stringByAppendingString:@"input text2\t"];
                
input = [input stringByAppendingString:@"input text3\t"];
                
NSLog(@"input text is \t %@", input);

你使用 stringByAppendingString將每個(gè)用戶輸入拼接成一個(gè)字符串,??你完成了這個(gè)需求,但是呢,這樣效率比較低。看下面的代碼

NSString * input = @"";
        
NSLog(@"input address %p", input); // input address 0x102015050

input = [input stringByAppendingString:@"input text1\t"];
        
NSLog(@"input address %p", input);// input address 0x102015090
        
input = [input stringByAppendingString:@"input text2\t"];
        
NSLog(@"input address %p", input);//input address 0x7fedea003d50
        
input = [input stringByAppendingString:@"input text3\t"];
        
NSLog(@"input address %p", input);//input address 0x7fedea003ed0
        
NSLog(@"input text is \t %@", input);

觀察下 input的地址變化,剛始是 0x102015050,后面你每執(zhí)行一次 stringByAppendingString,地址就變了一次,結(jié)合我上面提到的不可變特性就很容易解釋了

NSString 本質(zhì)就是不可變的,你調(diào)用了 stringByAppendingString函數(shù)返回的是一個(gè)新的對(duì)象,可想而知,太多的stringByAppendingString調(diào)用必然會(huì)引起性能問(wèn)題,因?yàn)閮?nèi)存分配是很消耗資源的,我們應(yīng)該盡量避免。

解決方案當(dāng)然就是可辨字符串類型 NSMutableString,如下代碼

NSMutableString * input = [NSMutableString stringWithCapacity:1024];
        
NSLog(@"input address %p", input);

[input appendString:@"input text1\t"];
        
NSLog(@"input address %p", input);
        
[input appendString:@"input text2\t"];
        
NSLog(@"input address %p", input);
        
[input appendString:@"input text3\t"];
        
NSLog(@"input address %p", input);
        
NSLog(@"input text is \t %@", input);

輸出信息:

2016-09-29 17:55:21.604 Untitled[71051:1785450] input address 0x7ff6064035f0
2016-09-29 17:55:21.604 Untitled[71051:1785450] input address 0x7ff6064035f0
2016-09-29 17:55:21.604 Untitled[71051:1785450] input address 0x7ff6064035f0
2016-09-29 17:55:21.604 Untitled[71051:1785450] input address 0x7ff6064035f0
2016-09-29 17:55:21.605 Untitled[71051:1785450] input text is    input text1    input text2 input text3

可變與不可變的區(qū)別在與內(nèi)存管理方式上,可變類型會(huì)管理一塊內(nèi)存用于存放數(shù)據(jù)(在這里是字符),比如上面我們分配了1024個(gè)字符,那么當(dāng)前數(shù)據(jù)如果沒(méi)超過(guò)1024個(gè)字符限制的話,NSMutableString 直接往里填就可以了,如果超出,那么會(huì)像NSString一樣,重新開辟一段更大的內(nèi)存,然后把原來(lái)的字符逐個(gè)拷貝到新的地址,但相對(duì)來(lái)說(shuō),內(nèi)存分配的次數(shù)大大減少了,性能也就提高了。

當(dāng)你需要頻繁變動(dòng)字符串的時(shí)候,NSMutableString可以極大的提高性能,但是需要耗費(fèi)更大的內(nèi)存,造成浪費(fèi),所以在實(shí)際編程的時(shí)候還是需要取舍到底哪個(gè)類比較適合當(dāng)前業(yè)務(wù)。

另外因?yàn)镹SMutableString是NSString的子類,所以NSMutableString的實(shí)例可以給NSString的變量賦值,這樣會(huì)導(dǎo)致NSMutableString實(shí)例改變了內(nèi)容,NSString的變量也改變的情況,這在某些情況下是錯(cuò)的,這個(gè)時(shí)候應(yīng)該使用 copy關(guān)鍵字來(lái)將 NSMutableString 的實(shí)例字符串拷貝一份到 NSString實(shí)例里面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容