Last active
October 24, 2019 10:05
-
-
Save davidleee/48322904c70b4ce82facc2c77c1566d5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
extension String { | |
var glyphCount: Int { | |
let richText = NSAttributedString(string: self) | |
let line = CTLineCreateWithAttributedString(richText) | |
return CTLineGetGlyphCount(line) | |
} | |
var isSingleEmoji: Bool { | |
return glyphCount == 1 && containsEmoji | |
} | |
var containsEmoji: Bool { | |
return unicodeScalars.contains { $0.isEmoji } | |
} | |
var containsOnlyEmoji: Bool { | |
return !isEmpty | |
&& !unicodeScalars.contains(where: { | |
!$0.isEmoji | |
&& !$0.isZeroWidthJoiner | |
}) | |
} | |
// The next tricks are mostly to demonstrate how tricky it can be to determine emoji's | |
// If anyone has suggestions how to improve this, please let me know | |
var emojiString: String { | |
return emojiScalars.map { String($0) }.reduce("", +) | |
} | |
var emojis: [String] { | |
var scalars: [[UnicodeScalar]] = [] | |
var currentScalarSet: [UnicodeScalar] = [] | |
var previousScalar: UnicodeScalar? | |
for scalar in emojiScalars { | |
if let prev = previousScalar, !prev.isZeroWidthJoiner && !scalar.isZeroWidthJoiner { | |
scalars.append(currentScalarSet) | |
currentScalarSet = [] | |
} | |
currentScalarSet.append(scalar) | |
previousScalar = scalar | |
} | |
scalars.append(currentScalarSet) | |
return scalars.map { $0.map{ String($0) } .reduce("", +) } | |
} | |
fileprivate var emojiScalars: [UnicodeScalar] { | |
var chars: [UnicodeScalar] = [] | |
var previous: UnicodeScalar? | |
for cur in unicodeScalars { | |
if let previous = previous, previous.isZeroWidthJoiner && cur.isEmoji { | |
chars.append(previous) | |
chars.append(cur) | |
} else if cur.isEmoji { | |
chars.append(cur) | |
} | |
previous = cur | |
} | |
return chars | |
} | |
} | |
extension UnicodeScalar { | |
var isEmoji: Bool { | |
switch value { | |
case 0x1F600...0x1F64F, // Emoticons | |
0x1F300...0x1F5FF, // Misc Symbols and Pictographs | |
0x1F680...0x1F6FF, // Transport and Map | |
0x1F1E6...0x1F1FF, // Regional country flags | |
0x2600...0x26FF, // Misc symbols | |
0x2700...0x27BF, // Dingbats | |
0xFE00...0xFE0F, // Variation Selectors | |
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs | |
127000...127600, // Various asian characters | |
// 65024...65039, // Variation selector, duplicate to 0xFE00...0xFE0F | |
9100...9300, // Misc items | |
8400...8447: // Combining Diacritical Marks for Symbols | |
return true | |
default: return false | |
} | |
} | |
var isZeroWidthJoiner: Bool { | |
return value == 8205 | |
} | |
} |
extension String {
var countWithEmoji: Int {
var count = 0
for substring in self {
if substring.isEmoji {
count += 2
} else {
count += 1
}
}
return count
}
}
extension Character {
var isEmoji: Bool {
for scalar in unicodeScalars {
if scalar.isEmoji {
return true
}
}
return false
}
}
extension UnicodeScalar {
var isEmoji: Bool {
switch value {
case 0x1F600...0x1F64F, // Emoticons
0x1F300...0x1F5FF, // Misc Symbols and Pictographs
0x1F680...0x1F6FF, // Transport and Map
0x1F1E6...0x1F1FF, // Regional country flags
0x2600...0x26FF, // Misc symbols
0x2700...0x27BF, // Dingbats
0xFE00...0xFE0F, // Variation Selectors
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
127000...127600, // Various asian characters
65024...65039, // Variation selector
9100...9300, // Misc items
8400...8447: // Combining Diacritical Marks for Symbols
return true
default:
return false
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some emojis consist of two unicodeScalar value instead of one, e.g.☺️ is the combination of 9786 & 65039.
Therefore the number of emojis within a string is not always equals to the number of unicodeScalars it contains.
If you want to know how many emojis a string contains, try look into
Character
, it always sees an emoji as one character.