Anastasiia
Anastasiia

Reputation: 124

🫥 Swift isEmoji isEmojiPresentation

Why method isEmojiPresentation return false?

"🫥".unicodeScalars.first?.properties.isEmoji // Optional(false)

"🫥".unicodeScalars.first?.properties.isEmojiPresentation // Optional(false)

enter image description here

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:

enter image description here

Upvotes: 4

Views: 743

Answers (2)

Graham Lea
Graham Lea

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

Daniel Klöck
Daniel Klöck

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

Related Questions