NSString中 componentsSeparatedByString存在的陷阱

原文地址:
http://blog.csdn.net/geniuslinchao/article/details/7416339
這兩天在對一個國外達人提供的IOS富文本庫做一些封裝和修改,在用這個庫將文本轉換成HTML的過程中發現一個奇怪的BUG,就是當文本中存在空行的時候,輸出就肯定錯誤。在源代碼中轉了一下午都沒找到原因,因爲項目進度緊張所以把BUG提供給了庫的作者。給作者發完郵件,又在源代碼中找了一次,其中有一行代碼很不起眼,我看了好幾遍都沒懷疑到這行代碼,如下:
NSArray *paragraphs = [plainString componentsSeparatedByString:@"\n"];
....
for (NSString *oneParagraph in paragraphs)
{
...
if (oneParagraph == [paragraphs lastObject] && !paragraphRange.length)   //就是這一句
{
continue;
}
...
}
其實就是用NSString中的componentsSeparatedByString函數將文本以換行符分隔成一個數組,然後遍歷數組,數組中每段文本當做一個<p>標籤處理。這段代碼如果憑肉眼看怎麼都沒問題,但如果單步調試的話就可以發現問題。關鍵就在於oneParagraph == [paragraphs lastObject], 判斷當前是否是數組中最後一個元素(地址比較)。用一個例子就可以發現這樣判斷是不可靠的。(注:該庫作者第二天就給我回復了郵件,他還就這個Bug寫了篇博客,下面的例子來源於此 http://www.cocoanetics.com/2012/03/beware-of-nsstring-optimizations/)
例子:
NSString *text =@"one,,one,,one,";
    NSArray *components = [text componentsSeparatedByString:@","];
    
    for (NSString *oneString in components)
    {
        NSLog(@"'%@' = %@ %p", oneString, [oneString class], oneString);
    }

輸出結果如下:
'one' = __NSCFString 0x176960
'' = __NSCFConstantString 0x3eeea9d0
'one' = __NSCFString 0x177960
 '' = __NSCFConstantString 0x3eeea9d0
 'one' = __NSCFString 0x177970
 '' = __NSCFConstantString 0x3eeea9d0
可以發現,幾個空串的地址是一樣的!如果用oneParagraph == [paragraphs lastObject]判斷最後一個元素的話,第二和第三個空串都會被跳過去!!!
最後解決的辦法就是用數組下標判斷,i == [paragraphs count] - 1。 雖然不優雅,但可以保證不出錯誤。
編譯器這麼做肯定有它的道理,因爲爲所有空串分配單獨內存也沒多大必要,但這個陷阱會讓很多人受到傷害。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章