Last active
September 19, 2024 14:13
-
-
Save krummler/8aac35e2446d34791ad8e95d792aaa38 to your computer and use it in GitHub Desktop.
Emoji checking, with some legacy code
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 Foundation | |
extension UnicodeScalar { | |
/// Note: This method is part of Swift 5, so you can omit this. | |
/// See: https://developer.apple.com/documentation/swift/unicode/scalar | |
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 | |
0xE0020...0xE007F, // Tags | |
0xFE00...0xFE0F, // Variation Selectors | |
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs | |
0x1F018...0x1F270, // Various asian characters | |
0x238C...0x2454, // Misc items | |
0x20D0...0x20FF: // Combining Diacritical Marks for Symbols | |
return true | |
default: return false | |
} | |
} | |
var isZeroWidthJoiner: Bool { | |
return value == 8205 | |
} | |
} | |
extension String { | |
// Not needed anymore in swift 4.2 and later, using `.count` will give you the correct result | |
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gives you the follow results: