iOS - NSString 與 Emoji

背景

????前些陣子遇到一個需求,一個文本剪輯器,發(fā)布時需要統(tǒng)計除 Emoji 外的字數(shù),于是求助度娘,以 ”NSString 是否包含 Emoji“ 為關鍵字找到不同的文章都給出了一模一樣的解決方案,但實際測試中,這個方案隨著 iOS 版本的更迭早已不再適用

解決方案

????在這篇文章里面: iOS - 判斷 NSString 字符串是否包含 Emoji

原理

????想做 Emoji 判斷首先需要要有兩個前置的知識儲備,Unicode 編碼方式和原理,以及 NSString 和 Unicode 的關系。

Unicode

????限于篇幅,關于 Unicode 的簡介和發(fā)展歷程可以參考我的這篇文章:Unicode 簡介與發(fā)展歷程,里面有著詳細的 UTF 編碼原理介紹。

????此外,網(wǎng)絡上面也有著許多和 Unicode 相關的大佬們的文章可以閱讀。Unicode 官網(wǎng)里面更有著非常詳細的介紹和細節(jié)。

NSString 與 UTF

????在了解了 Unicode 和 UTF 編碼原理之后,只需要再了解 NSString 使用了那種編碼方式就很容易找出解決方案。而 NSString 的編碼方式在 NSString.h 的頭文件中有明確的說明:

/* The unichar type represents a single UTF-16 code unit in an NSString. Although many human-readable characters are representable with a single unichar, some  such as Emoji may span multiple unichars. See discussion above.
*/
typedef unsigned short unichar;

????在明確了 NSString 使用 UTF-16 的編碼方式之后,結(jié)合 UTF-16 的編碼原理,可以得到 NSString 和碼點之間的互相的轉(zhuǎn)換關系如下:

/*
 Nsstring 轉(zhuǎn)換為碼點
 */
- (int)stringToCodePoint:(NSString *)string {
    const unichar hs = [string characterAtIndex:0];
    if (0xd800 <= hs && hs <= 0xdbff) {
        if (string.length > 1) {
            const unichar ls = [string characterAtIndex:1];
            const int codepoint = (((int)hs - 0xd800) * 0x400) + ((int)ls - 0xdc00) + 0x10000;
            return codepoint;
        } else {
            return 0;
        }
    } else {
        return (int)hs;
    }
}

/*
 碼點轉(zhuǎn)換為 NSString
 */
- (NSString *)stringFromCodePoint:(int)codePoint {
    if (codePoint <= 0xFFFF)
    {
        return [[NSString alloc] initWithBytes:&codePoint length:sizeof(codePoint) encoding:NSUTF8StringEncoding];
    }
    else if (0x10000 <= codePoint && codePoint <= 0x10FFFF)
    {
        int symbol = ((((0x808080F0 | (codePoint & 0x3F000) >> 4) | (codePoint & 0xFC0) << 10) | (codePoint & 0x1C0000) << 18) | (codePoint & 0x3F) << 24);
        return [[NSString alloc] initWithBytes:&symbol length:sizeof(symbol) encoding:NSUTF8StringEncoding];
    }
    else
    {
        return nil;
    }
}

????了解了 NSString 和 Unicode 碼點之間的轉(zhuǎn)換關系,就可以理解上面解決方案里面提供的方案。

題外話

????實際上,Emoji 的編碼方式遠比我們想象的要復雜得多,盡管上述的解決方案可以解決問題,但是在做碼點和 NSString 的互相轉(zhuǎn)化過程中,發(fā)現(xiàn) Emoji 除了有單碼點表示的方法之外,還有多碼點組合字符的形式。

????這篇文章里面會詳細的介紹 Unicode 與 Emoji 的組合字:Unicode 和 Emoji 中的組合字符

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

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

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