Following this post I tried to update the code from Swift 2.0 to Swift 5.0 to check which emojis have skin tones available or not and other variations already present. My updated code in detail:
extension String {
var emojiSkinToneModifiers: [String] {
return [ "π»", "πΌ", "π½", "πΎ", "πΏ" ]
}
var emojiVisibleLength: Int {
var count = 0
enumerateSubstrings(in: startIndex..<endIndex, options: .byComposedCharacterSequences) { (_, _, _, _) in
count = count + 1
}
return count
}
var emojiUnmodified: String {
if self.count == 0 {
return ""
}
let range = String(self[..<self.index(self.startIndex, offsetBy: 1)])
return range
}
var canHaveSkinToneModifier: Bool {
if self.count == 0 {
return false
}
let modified = self.emojiUnmodified + self.emojiSkinToneModifiers[0]
return modified.emojiVisibleLength == 1
}
}
And use this with an array:
let emojis = [ "π", "ππΏ", "πΈ" ]
for emoji in emojis {
if emoji.canHaveSkinToneModifier {
let unmodified = emoji.emojiUnmodified
print(emoji)
for modifier in emoji.emojiSkinToneModifiers {
print(unmodified + modifier)
}
} else {
print(emoji)
}
}
The output: πππ»ππΌππ½ππΎππΏ ππΏππΏπ»ππΏπΌππΏπ½ππΏπΎππΏπΏ πΈπΈπ»πΈπΌπΈπ½πΈπΎπΈπΏ assigns variations to emojis that do not have them or that already is instead of: πππ»ππΌππ½ππΎππΏ ππΏ πΈ
I suppose enumerateSubstringsInRange
is incorrect and self.characters.count
now became self.count
easy and correct to count one emoji (composed) compared to before Swift 4 but maybe not useful in this case. What am I not seeing wrong?
Thanks
A "hack" would be to compare the visual representation of a correct emoji (like "πΈ") and a wanna-be emoji (like "πΈπ½").
I've modified your code here and there to make it work:
extension String {
static let emojiSkinToneModifiers: [String] = ["π»", "πΌ", "π½", "πΎ", "πΏ"]
var emojiVisibleLength: Int {
var count = 0
let nsstr = self as NSString
let range = NSRange(location: 0, length: nsstr.length)
nsstr.enumerateSubstrings(in: range,
options: .byComposedCharacterSequences)
{ (_, _, _, _) in
count = count + 1
}
return count
}
var emojiUnmodified: String {
if isEmpty {
return self
}
let string = String(self.unicodeScalars.first!)
return string
}
private static let emojiReferenceSize: CGSize = {
let size = CGSize(width : CGFloat.greatestFiniteMagnitude,
height: CGFloat.greatestFiniteMagnitude)
let rect = ("π" as NSString).boundingRect(with: size,
options: .usesLineFragmentOrigin,
context: nil)
return rect.size
}()
var canHaveSkinToneModifier: Bool {
if isEmpty {
return false
}
let modified = self.emojiUnmodified + String.emojiSkinToneModifiers[0]
let size = (modified as NSString)
.boundingRect(with: CGSize(width : CGFloat.greatestFiniteMagnitude,
height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
context: nil).size
return size == String.emojiReferenceSize
}
}
Let's try it out:
let emojis = [ "π", "ππΏ", "πΈ" ]
for emoji in emojis {
if emoji.canHaveSkinToneModifier {
let unmodified = emoji.emojiUnmodified
print(unmodified)
for modifier in String.emojiSkinToneModifiers {
print(unmodified + modifier)
}
} else {
print(emoji)
}
print("\n")
}
And voila!
π ππ» ππΌ ππ½ ππΎ ππΏ π ππ» ππΌ ππ½ ππΎ ππΏ πΈ
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With