更新:網絡上流傳的 emoji 代碼點不太完整,我按照維基百科的資料重新整理了一下,文中的 Swift 版本代碼已更新。
很多時候我們需要判斷一個字符、或者說是一句話裡是不是包含了emoji,使用 Swift 語言開發 app 也不例外,比如可以使用正則表達式——但很遺憾,似乎不同的語言對於正則表達式的支持區別, \u 這個功能不是到哪都好使的,所以最簡單粗暴的辦法,我們弄一個字符串,它包含了所有可能會用到的 emoji,然後去檢索它:
1 2 3 4 |
var emojis = "???" if let range = emojis.range(of:"xxx") { } |
其實吧,說句良心哈,效率還不錯……當然了,這樣的結果就是你的列表得時常更新——同時你還得忍受 Xcode 卡得一逼的狀態。
使用遍歷
所以,網上有一個用 OC 實現的擴展,似乎流傳很廣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
@implementation NSString (Emoji) + (BOOL)stringContainsEmoji:(NSString *)string { __block BOOL returnValue = NO; [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { const unichar hs = [substring characterAtIndex:0]; if (0xd800 <= hs && hs <= 0xdbff) { if (substring.length > 1) { const unichar ls = [substring characterAtIndex:1]; const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000; if (0x1d000 <= uc && uc <= 0x1f77f) { returnValue = YES; } } } else if (substring.length > 1) { const unichar ls = [substring characterAtIndex:1]; if (ls == 0x20e3) { returnValue = YES; } } else { if (0x2100 <= hs && hs <= 0x27ff) { returnValue = YES; } else if (0x2B05 <= hs && hs <= 0x2b07) { returnValue = YES; } else if (0x2934 <= hs && hs <= 0x2935) { returnValue = YES; } else if (0x3297 <= hs && hs <= 0x3299) { returnValue = YES; } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) { returnValue = YES; } } }]; return returnValue; } |
其實它的原理還是去匹配 Emoji 所在區間,所以,如果我們應用上 Swift 語句以及其特性,那麼 Swift 版本就是這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
extension String { var containsEmoji: Bool { for scalar in unicodeScalars { switch scalar.value { case 0x00A0...0x00AF, 0x2030...0x204F, 0x2120...0x213F, 0x2190...0x21AF, 0x2310...0x329F, 0x1F000...0x1F9CF: return true default: continue } } return false } } |
?是不是很簡潔?
本文由 落格博客 原創撰寫:落格博客 » Swift 中判斷字符串是否有 Emoji 表情
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2504.html
為什麼不用正則?
用正則原理也是一樣,匹配emoji區間範圍,可以用正則啊。只是寫這篇文章的時候我沒想到可以用正則,我對這個也不熟練罷了。
不過由於emoji一直在演進,最終的結果是我選擇將 emoji 單獨存放並記錄數據來源,從根本上對他們進行了區分,不需要判斷了。(當然這是針對我自己的業務邏輯)
由於 emoji 是變長的,我覺得還是反過來判斷ASCII字符比較容易,如果包含中文就再加上中文的字符區間好了。
老鐵你發的這個有bug哦。在真機鍵盤的 九鍵拼音中。 你的檢測不准、
是的,這個並不能覆蓋所有的emoji範圍,因為emoji範圍本身是演進擴大的,你要根據變化來改這個值的範圍,比如說我補充瞭如下的代碼,這幾個就不在正文那個範圍之內的。
如果 (自.範圍(的: "8️⃣") != 零) { 返回 true } 其他 如果 (自.範圍(的: "0️⃣") != 零) { 返回 true } 其他 如果 (自.範圍(的: "6️⃣") != 零) { 返回 true }