Swiftで文字列の中の絵文字を判定できないかを調べてみました。
結論
下のようにisEmojiPresentation、isEmojiModifier、isEmojiModifierBaseを使う事で判定できるようです。
各メソッドの内容は下部の調査内容に記載しました。
let inputText = "Some 🕵string 😂😂😂 with 👹👹 👹 emoji 🖐" print(inputText.unicodeScalars.filter { !$0.properties.isEmojiPresentation && !$0.properties.isEmojiModifier && !$0.properties.isEmojiModifierBase }.reduce("", { $0 + String($1) })))
調査経緯
絵文字について調べたところisEmojiPresentationというメソッドがあったので試してみました。
Swift - Replacing emojis in a string with whitespace - Stack Overflow
このメソッドを使って絵文字を除外してみました。
isEmojiPresentationはUnicode.Scalar.Propertiesクラスのメソッドなので文字列からPropertiesを取り出して再度結合する必要があります。
let inputText = "Some 🖐string 😂😂😂 with 👹👹 👹 emoji 🖐" let textWithoutEmoij = inputText.unicodeScalars.filter { !$0.properties.isEmojiPresentation }.reduce("") { $0 + String($1) } print(textWithoutEmoij)
結果は下の通りです。
🖐だけは除外することができませんでした。
除外できない原因を探る為、unicodeScalarsで取得したScalarを一つ一つ出力してみました。
let inputText = "Some 🖐string 😂😂😂 with 👹👹 👹 emoji 🖐" inputText.unicodeScalars.forEach { print($0.properties) }
結果は下の通りです。
手の絵文字も正しく取得できているようでした。
良く分からないのでisEmojiPresentationのメソッドの説明を確認しました。
それによるとEmoji_Presentationに含まれる絵文字ならtrueになるようです。
A Boolean value indicating whether the scalar is one that should be rendered with an emoji presentation, rather than a text presentation, by default. Scalars that have default to emoji presentation can be followed by U+FE0E VARIATION SELECTOR-15 to request the text presentation of the scalar instead. Likewise, scalars that default to text presentation can be followed by U+FE0F VARIATION SELECTOR-16 to request the emoji presentation. This property corresponds to the "Emoji_Presentation" property in the [Unicode Standard](http://www.unicode.org/versions/latest/).
🖐はEmoji_Presentationにない可能性も考えてUnicodeのサイトを確認したのですが🖐は含まれていました。
🖐が異字体なこと(🖐🏾などのカラーバリエーションがある事)が原因の可能性も考えて他の異字体絵文字でも試してみました。
print("🕵".unicodeScalars) print("🕵".unicodeScalars.first?.properties.isEmojiPresentation)
試した所、この絵文字もisEmojiPresentationで判別できない事が分かりました。
異字体はisEmojiPresentationを使った判別は難しいようです。
ドキュメント見ていた所、isEmojiModifierBaseとisEmojiModifierというメソッドがあったので動かしてみました。
検証コードは下の通りです。
print("😂".unicodeScalars) print("😂".unicodeScalars.map { $0.properties.isEmojiPresentation }) print("😂".unicodeScalars.map { $0.properties.isEmojiModifier }) print("😂".unicodeScalars.map { $0.properties.isEmojiModifierBase }) print("🕵".unicodeScalars) print("🕵".unicodeScalars.first?.properties.isEmojiPresentation) print("🕵".unicodeScalars.map { $0.properties.isEmojiModifier }) print("🕵".unicodeScalars.map { $0.properties.isEmojiModifierBase }) print("🖐".unicodeScalars) print("🖐".unicodeScalars.first?.properties.isEmojiPresentation) print("🖐".unicodeScalars.map { $0.properties.isEmojiModifier }) print("🖐".unicodeScalars.map { $0.properties.isEmojiModifierBase }) print("🖐🏾".unicodeScalars) print("🖐🏾".unicodeScalars.first?.properties.isEmojiPresentation) print("🖐🏾".unicodeScalars.map { $0.properties.isEmojiModifier }) print("🖐🏾".unicodeScalars.map { $0.properties.isEmojiModifierBase })
結果は下の通りです。
異字体はisEmojiModifierBaseがtrueになっていました。
🖐🏾の結果を見た限り、異字体の色を決める部分はisEmojiModifierで判定できるようです。
上記メソッドを使って下のようにコードを修正しました。
let inputText = "Some 🕵string 😂😂😂 with 👹👹 👹 emoji 🖐" print(inputText.unicodeScalars.filter { !$0.properties.isEmojiPresentation && !$0.properties.isEmojiModifier && !$0.properties.isEmojiModifierBase }.reduce("", { $0 + String($1) })))
動かしてみた所、すべての絵文字を除外できるようになりました。
余談ですがUnicode.Scalar.PropertiesにはisEmojiというメソッドもあります。
こちらは異字体も絵文字として判定するのですが、0などの絵文字以外も絵文字扱いしてしまうので使用しませんでした。
print("0".unicodeScalars.map { $0.properties.isEmojiPresentation }) // true