Swift 5 では、文字列内の各文字のUnicodeプロパティを検査できるようになりました
これにより、各文字に便利なisEmoji
変数が使用できます
絵文字にはUTF-16のUnicodeであり2バイトと4バイトの絵文字があります。
問題:
数字の0 ~ 9などの2バイトの絵文字に変換できるすべての文字に対してisEmoji
が、true
を返すことです。
回避策:
修飾子を必要としないUTF16絵文字の最初のインスタンス"0x203C"未満の文字には絵文字修飾子が添付されていることを確認します。
extension String {
func containsEmoji() -> Bool {
contains { $0.isEmoji }
}
func containsOnlyEmojis() -> Bool {
return count > 0 && !contains { !$0.isEmoji }
}
}
extension Character {
// `isEmoji`は、数字の「3」などの修飾子を追加することで絵文字に変換できるすべての文字に対してtrueとなります。
// これを回避するために、"0x203C"未満の文字には絵文字修飾子が添付されていることを確認します。
// "0x203C"は、修飾子を必要としないUTF16絵文字の最初のインスタンスです。
var isEmoji: Bool {
guard let scalar = unicodeScalars.first else { return false }
return scalar.properties.isEmoji && (scalar.value >= 0x203C || unicodeScalars.count > 1)
}
}
以下のような結果となります
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true