4

I am having some issues adding a skin tone modifier to an emoji in my app. For example, if I use:

let text = "" + "" 

It prints

However, for other emojis it does not work. For example:

let text = "‍" + ""

Prints ‍

What is the proper way to add a skin tone modifier to an emoji?

Lucas Azzopardi
  • 1,131
  • 2
  • 11
  • 21

1 Answers1

10

Adding the skin tone modifier only works if the preceding character is a plain Emoji character. It turns out, your "‍" is actually made up of 3 characters. The plain woman emoji U+1F469 (), followed by U+200D, and finally, the hair modifier U+1F9B0 ().

You can see this with:

print(Array("‍".unicodeScalars)) // ["\u{0001F469}", "\u{200D}", "\u{0001F9B0}"]

So trying to add the skin tone modifier after the hair modifier doesn't work. The skin tone modifier needs to be immediately after the base Emoji.

Here's a String extension that will apply a skin tone to characters even if they already have a skin tone or other modifiers.

extension String {
    func applySkinTone(_ tone: String) -> String {
        guard tone.count == 1 && self.count > 0 else { return self }
        let minTone = Unicode.Scalar(0x1F3FB)!
        let maxTone = Unicode.Scalar(0x1F3FF)!
        guard let toneChar = tone.unicodeScalars.first, minTone...maxTone ~= toneChar else { return self }

        var scalars = Array(self.unicodeScalars)
        // Remove any existing tone
        if scalars.count >= 2 && minTone...maxTone ~= scalars[1] {
            scalars.remove(at: 1)
        }
        // Now add the new tone
        scalars.insert(toneChar, at: 1)

        return String(String.UnicodeScalarView(scalars))
    }
}

print("".applySkinTone("")) // 
print("‍".applySkinTone("")) // ‍

Note that this code does not do any validation that the original string supports a skin tone.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • This answer is good for setting skin tone of individuals but it doesn’t work with some couples. Any idea how to make it work with couples? – Kurt L. Aug 16 '22 at 04:19