Created
May 27, 2019 07:38
-
-
Save SergLam/c0f3da1018ef80b3c54b3626162fb6e9 to your computer and use it in GitHub Desktop.
Swift - check if string contains emoji character
This file contains 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
// https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji | |
import Foundation | |
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 | |
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