通常來講,Swift 裡的 String 是和 的NSString 橋接的,比如我曾寫過 NSString 和 String 究竟 有什麼區別 ?,總之這裡我們主要來討論一下,String 的 計數 和 的NSString 的 長度 到底有什麼區別。
String.count
String.計數 實際上是 String.人物.計數 (Swift 早期版本),Swift 裡的 String ,早期 計數 屬性就是單純的字符數量,這和 的NSString 是一樣的,但很快就加入了擴展字形集群特性,比如一個 Emoji 表情,它的編碼長度是普通字符的兩倍,但這是視覺上的【一個】字符,於是它在 String 裡算【一個】字符。
比如:
1 2 3 4 5 |
let s = "🐶" print(s.count) // result is 1 |
需要注意的是斯威夫特的使用延長字形集群 <跨度 類="預">字符</跨度> 值意味著字符串連接和修改可能不總是影響一個字符串的字符計數.
注意 Swift 為 字符 值使用的擴展字形集群意味著字符串的創建和修改可能不會總是影響字符串的字符統計數。
NSString.length
對於很有歷史感的 的NSString 來說,就沒那麼複雜了,它就是字符的數組,所以它只會單純計算字符數量,由於一個 Emoji 就是用兩個字符的長度表達的,所以在這裡,長度為 2 :
1 2 3 4 5 |
let s = "🐶" print((s as NSString).length) //result is 2 |
兼容性
如果不注意這個問題,就會遇到很多奇怪的小錯誤,比如在設定富文本顏色的時候,會導致文本末尾異常,會導致 Emoji 亂碼等等。因為富文本是 NSAttributedString ,它的長度計算是基於 UTF16 字符長度的,而不是合併後的【視覺】字符長度:
1 2 3 4 5 6 7 8 9 10 |
let s = "🐶" let att = NSMutableAttributedString(string: s) att.addAttributes([.foregroundColor:NSColor.red], range: NSRange(location: 0, length: s.count)) print(att) // result is: �{ NSColor = "sRGB IEC61966-2.1 colorspace 1 0 0 1"; }�{ } |
注意高亮行,這裡 NSRange(位置: 0, 長度: 小號.計數) 使用了 String 的 計數 屬性,讀出的長度應該是 1 ,但 NSMutableAttributedString 是以 UTF16 字符長度做計算,所以字符串長度應該是 2 ,結果導致為半個 Emoji 字符添加顏色,輸出內容為亂碼。
1 2 3 4 5 6 7 8 9 |
let s = "🐶" let att = NSMutableAttributedString(string: s) att.addAttributes([.foregroundColor:NSColor.red], range: NSRange(location: 0, length: (s as NSString).length)) print(att) //result is: 🐶{ NSColor = "sRGB IEC61966-2.1 colorspace 1 0 0 1"; } |
將字符串轉換為 的NSString 後獲取 長度 則得到了正確結果。
Swift 裡的 UTF16 字符串長度
那麼,每次使用,都要明顯地寫成 ("" 如 的NSString).長度 的形式嗎?雖然寫個 延期 也不是不行,不過,我們其實也可以直接從 String 原生地獲取這個長度:
1 2 3 4 5 |
let s = "🐶" print(s.utf16.count) //result is 2 |
討論
String 和 的NSString 有很多名稱類似但功能相同的方法,但得到的結果卻可能並不完全一致,要小心 Swift 對字符串的處理,這些問題往往會在一些細節的地方體現出來,比如輸入法移動光標的 API,其中移動 1 長度,是 1 UTF16 字符長度,比如 Emoji,計數是 2 而不是 1,如果不注意這個細節,就會導致一些自動化功能在遇到 Emoji 表情或者某些生僻中文字符時計算出錯,因為這些符號視覺上是一個字,但實際上使用了可變長的多個 UTF16 字符長度。
延伸閱讀
HTTPS://stackoverflow.com/a/36268059
HTTPS://stackoverflow.com/a/29833042
HTTPS://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html
HTTPS://www.cnswift.org/strings-and-characters
本文由 落格博客 原創撰寫:落格博客 » String.count VS NSString.length
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/3253.html