Reputation: 124
Why method isEmojiPresentation return false?
"🫥".unicodeScalars.first?.properties.isEmoji // Optional(false)
"🫥".unicodeScalars.first?.properties.isEmojiPresentation // Optional(false)
Docs
isEmoji - https://developer.apple.com/documentation/swift/unicode/scalar/properties-swift.struct/isemoji
isEmojiPresentation - https://developer.apple.com/documentation/swift/unicode/scalar/properties-swift.struct/isemojipresentation
UDP:
Upvotes: 4
Views: 743
Reputation: 6333
Checking only isEmoji
or isEmojiPresentation
is not enough to know how a character in text will be presented to the user. You also (at least)* need to check whether there are variation selectors in the character that change how it should be presented. For example, some emoji are presented as text by default, but there is a scalar that can be added to present them as an image, and often when an emoji is input from the user (e.g. 🗑️), it is this emoji+variation sequence that is being generated. I'm sure the opposite example also exists, i.e. image by default but text variation specified.
Here's the code I'm using to detect if a character will be presented as an emoji image:
fileprivate let TEXT_VARIATION_SELECTOR = "\u{FE0E}".unicodeScalars.first
fileprivate let EMOJI_VARIATION_SELECTOR = "\u{FE0F}".unicodeScalars.first
extension Character {
var presentsEmoji: Bool {
var emojiByDefault = false
for s in unicodeScalars {
if s.properties.isEmojiPresentation { emojiByDefault = true }
if s == EMOJI_VARIATION_SELECTOR { return true }
if s == TEXT_VARIATION_SELECTOR { return false }
}
return emojiByDefault
}
}
*
I say "at least" because I'm not an expert on Unicode. I've figured out enough that the above satisfies my main use case, whereas trying to just use isEmoji
and isEmojiPresentation
did not.
Upvotes: 0
Reputation: 21137
From the isEmoji documentation you posted:
testing isEmoji alone on a single scalar is insufficient to determine if a unit of text is rendered as an emoji; a correct test requires inspecting multiple scalars in a Character.
Therefore, you can use following code to check if there is an emoji presentation:
"🫥".unicodeScalars.contains(where: { $0.properties.isEmoji }) // true
"5".unicodeScalars.contains(where: { $0.properties.isEmoji }) // true, as expected (5️⃣)
"a".unicodeScalars.contains(where: { $0.properties.isEmoji }) // false
and this code to check if the default is the emoji presentation:
"🫥".unicodeScalars.contains(where: { $0.properties.isEmojiPresentation }) // true
"5".unicodeScalars.contains(where: { $0.properties.isEmojiPresentation }) // false
"a".unicodeScalars.contains(where: { $0.properties.isEmojiPresentation }) // false
Here is an extension for convenience:
extension Character {
var hasEmojiPresentation: Bool {
unicodeScalars.contains(where: { $0.properties.isEmoji })
}
var hasEmojiPresentationAsDefault: Bool {
unicodeScalars.contains(where: { $0.properties.isEmojiPresentation })
}
}
Usage:
Character("🫥").hasEmojiPresentation // true
Character("🫥").hasEmojiPresentationAsDefault // true
Character("5").hasEmojiPresentation // true
Character("5").hasEmojiPresentationAsDefault // false
Character("a").hasEmojiPresentation // false
Character("a").hasEmojiPresentationAsDefault // false
Note: The outcome may be different depending on the used Xcode version, since they contain different sets of emojis.
Upvotes: 4