Unicode in iOS

如何理解Unicode

  • Unicode是個通用字符集,涵蓋了全世界所有字符
  • 總范圍從U+0000~U+10FFFF夕冲,十六進(jìn)制表示锨咙,共1114112個字符眉踱,占用21位
  • 通過每個字符挤忙,在Unicode字符集中有個一個碼點(diǎn)(code points)對應(yīng),如U+F8FF表示蘋果的icon
  • Unicode之規(guī)定了字符到碼點(diǎn)的對應(yīng)谈喳,但并沒有規(guī)定在機(jī)器中如何存儲册烈,即1個字節(jié)肯定無法存儲所有字符,如果有多個字節(jié)叁执,程序去讀這些字節(jié)時茄厘,遇到多個字節(jié)表示一個字符的情況矮冬,程序怎么知道要一次多去多個字節(jié)
  • Unicode所有的字符被抽象成17個平面谈宛,每個平面包含了不同的字符Unicode表達(dá)
  • 0號平面叫做BMP(Basic Multilingual Plane),基本多文種平面胎署,包括了常用的字符
  • 為了兼容一些老的編碼系統(tǒng)吆录,有些字符看上去是一個,其實(shí)在Unicode中有多種表示形式
    • é琼牧,既可以用U+00E9表示恢筝,也可以用U+0065(小寫字母e)加上U+0301(尖括號)合成表示,這種叫做組合字符序列字符序列(ComposedString)
    • 上面é的例子巨坊,外觀一樣撬槽、含義也一樣的情況下,這兩個叫做標(biāo)準(zhǔn)等價(canonically equivalent)
    • 有的情況趾撵,外觀一樣侄柔,但意義卻不同,比如小寫的拉丁連字符(U+FB00)兩個小寫拉丁字母ff(U+0066 U+0066)占调,外觀相同暂题,但卻含義不同。這種只能叫做相容等價(compatibility equivalence)

UTF(Unicode Transformation Formats)

  • Unicode轉(zhuǎn)換格式究珊,這是將Unicode真正用到程序中的一步薪者,即規(guī)定了在內(nèi)存、磁盤中如何存儲Unicode碼
  • UTF-32剿涮,每個字符的Unicode碼點(diǎn)言津,都用32位來表示,由于32位>21位取试,所以程序自然知道如何讀取字符悬槽,但浪費(fèi)空間
  • 這里的32位,或者后面的UTF-16的16位想括,稱作碼元(code unit)
  • UTF-16陷谱,每個Unicode碼點(diǎn)用1-2個16位來表示,這時候就得規(guī)定讀取順序了,即字節(jié)順序標(biāo)記(BOM-Byte Order Mask)
  • 所以烟逊,當(dāng)使用UTF-16編碼時渣窜,一定要標(biāo)示字節(jié)讀取順序,一般寫到文本開頭位置的兩個字節(jié)宪躯。默認(rèn)不寫的話是使用高字節(jié)順序
  • UTF-8
    • 用1-4個字節(jié)標(biāo)示Unicode
    • UTF-8和ASCII的所有碼點(diǎn)完全重合
    • 不需要考慮字節(jié)讀取順序乔宿?UTF-8規(guī)定了字節(jié)讀取順序

NSString

  • iOS中表示Unicode中BMP的字符用\uxxxx,非BMP的要用\Uxxxxxxxx表示

    NSString *s = @"\U0001F30D";//??
    ```
    
  • C99不允許標(biāo)準(zhǔn)C字符集中的字符用\uxxxx這種形式表示访雪,所以在iOS中寫\u0041(Unicode表示大寫字母A)是不允許

  • 蘋果文檔中說NSStringUnicode表示為16位详瑞,這完全蘋果的錯誤睦刃,因?yàn)槲覀冎?code>Unicode是21位的裹芝,用16位怎么表示

  • 其實(shí)是NSString處理字符的任何方法都是以16位為基本處理單元

    • 那些少數(shù)的在Unicode中16位表示不過來的,在NSString中的length屬性就不是字符長度了
  • 前文提到了組合字符序列征字,NSString也提供了組合與非組合之間的轉(zhuǎn)換方法精置,用于在標(biāo)準(zhǔn)等價计寇、相容等價幾種情況下進(jìn)行切換

    [test precomposedStringWithCanonicalMapping];
    [test decomposedStringWithCanonicalMapping];
    
    [test precomposedStringWithCompatibilityMapping];
    [test decomposedStringWithCompatibilityMapping];
    
  • 官方建議使用NSString時,將字符串看做子字符串的序列脂倦,而不是字符的序列番宁,因?yàn)樗淖址腿藗兛吹降恼J(rèn)為的字符不是一回事。但如果看做子字符串來處理赖阻,則其內(nèi)部的方法會很好的兼容各種問題

  • NSString中能夠保證返回正確字符數(shù)的方法是

NSString *s = @"The weather on \U0001F30D is \U0001F31E today.";  
// The weather on ?? is ?? today.  
NSRange fullRange = NSMakeRange(0, [s length]);  
[s enumerateSubstringsInRange:fullRange  
                      options:NSStringEnumerationByComposedCharacterSequences  
                   usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop)
{
    NSLog(@"%@ %@", substring, NSStringFromRange(substringRange));
}];

Swift中的Unicode

  • Swift中String對Unicode的支持蝶押,不像OC中的NString。String的count能夠很好的計(jì)算字符個數(shù)火欧,因?yàn)闀紤]到unicdoe各種組合的情況
    • 當(dāng)然也就可以把字符串當(dāng)做字符的序列了棋电,單個字符也可以正確地進(jìn)行處理了
    • 正因?yàn)閺?fù)雜的Unicode各種情況,Swift中獲取子串或索引時布隔,就不能通過整型值來獲取了离陶。而是通過String.Index類型
  • Swift中進(jìn)行字符或字符串等價判斷時,Swift認(rèn)為標(biāo)準(zhǔn)等價才是相等衅檀,相容等價并不相等
    let latinCapitalLetterA: Character = "\u{41}"http://大寫拉丁字母A
    let cyrillicCapitalLetterA: Character = "\u{0410}"http://西里爾字母A
    print(latinCapitalLetterA + "-" + cyrillicCapitalLetterA)
    print(latinCapitalLetterA == cyrillicCapitalLetterA)
    //結(jié)果
    A-A
    false
    

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末招刨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哀军,更是在濱河造成了極大的恐慌沉眶,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杉适,死亡現(xiàn)場離奇詭異谎倔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)猿推,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門片习,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捌肴,“玉大人,你說我怎么就攤上這事藕咏∽粗” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵孽查,是天一觀的道長饥悴。 經(jīng)常有香客問我,道長盲再,這世上最難降的妖魔是什么西设? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮答朋,結(jié)果婚禮上贷揽,老公的妹妹穿的比我還像新娘。我一直安慰自己绿映,他們只是感情好擒滑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布腐晾。 她就那樣靜靜地躺著叉弦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪藻糖。 梳的紋絲不亂的頭發(fā)上淹冰,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音巨柒,去河邊找鬼樱拴。 笑死,一個胖子當(dāng)著我的面吹牛洋满,可吹牛的內(nèi)容都是我干的晶乔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼牺勾,長吁一口氣:“原來是場噩夢啊……” “哼正罢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起驻民,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤翻具,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后回还,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆泳,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年柠硕,在試婚紗的時候發(fā)現(xiàn)自己被綠了工禾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖闻葵,靈堂內(nèi)的尸體忽然破棺而出糙捺,到底是詐尸還是另有隱情,我是刑警寧澤笙隙,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布洪灯,位于F島的核電站,受9級特大地震影響竟痰,放射性物質(zhì)發(fā)生泄漏签钩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一坏快、第九天 我趴在偏房一處隱蔽的房頂上張望铅檩。 院中可真熱鬧,春花似錦莽鸿、人聲如沸昧旨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兔沃。三九已至,卻和暖如春级及,著一層夾襖步出監(jiān)牢的瞬間乒疏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工饮焦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怕吴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓县踢,卻偏偏與公主長得像转绷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子硼啤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容