'Number of emojis in a String?
With recently added iOS 9.1 emojis, and the availability of skin tones etc, how do you properly count the number of Emojis in a String, assuming the string is uniquely made out of emojis?
Keep in mind that the length of emojis can vary.
NSString.length or string.characters.count
"😀" returns 2
"✊🏿" returns 4
"🇧🇸" or "🇧🇸" or "🇧🇸🇧🇸🇧🇸🇧🇸🇧🇸🇧🇸" returns 1!
"👨👩👧👧" returns 4 (Should be normally displayed as 1 family emoji)
etc...
Solution 1:[1]
I make an extension of String to count number of emoji in a string:
extension String {
func countEmojiCharacter() -> Int {
func isEmoji(s:NSString) -> Bool {
let high:Int = Int(s.characterAtIndex(0))
if 0xD800 <= high && high <= 0xDBFF {
let low:Int = Int(s.characterAtIndex(1))
let codepoint: Int = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000
return (0x1D000 <= codepoint && codepoint <= 0x1F9FF)
}
else {
return (0x2100 <= high && high <= 0x27BF)
}
}
let nsString = self as NSString
var length = 0
nsString.enumerateSubstringsInRange(NSMakeRange(0, nsString.length), options: NSStringEnumerationOptions.ByComposedCharacterSequences) { (subString, substringRange, enclosingRange, stop) -> Void in
if isEmoji(subString!) {
length++
}
}
return length
}
}
Test:
let y = "xxx?????zzz"
print(y.countEmojiCharacter())
// result is 3
Solution 2:[2]
try this code snippet
extension String {
var composedCount : Int {
var count = 0
enumerateSubstringsInRange(startIndex..<endIndex, options: .ByComposedCharacterSequences) {_ in count++}
return count
}
}
: credit goes to ericasadun
Solution 3:[3]
You can use this code example or this pod.
To use it in Swift, import the category into the YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Then you can check the range for every emoji in your String:
let example: NSString = "string???????with?emojis??" //string with emojis
let emojiCount: NSInteger = example.emo_emojiCount() // count
print(emojiCount)
// Output: ["3"]
I created an small example project with the code above.
UPDATE
Running this code with >= iOS 8.3 will have an
// Output: ["3"]
Running this code with < iOS 8.3 will have an
// Output: ["7"]
This is because family emoji, skin tone and many others were introduced with iOS 8.3. So, a smaller iOS version are reading this emojis in a different way.
As a example, open this post in Safari, Firefox and Chrome to see the difference.
Solution 4:[4]
some situation(e.g. netty):
"???????".utf8.count
Solution 5:[5]
swift4 answer:
extension String {
var composedCount : Int {
var count = 0
enumerateSubstrings(in: startIndex..<endIndex, options: .byComposedCharacterSequences) { (_, _, _, _) in
count = count + 1
}
return count
}
}
Solution 6:[6]
Emojis, much like the unicode standard, are deceptively complicated. Skin tones, genders, jobs, groups of people, zero-width joiner sequences, flags (2 character unicode) and other complications can make emoji parsing messy. A Christmas Tree, a Slice of Pizza, or a Pile of Poop can all be represented with a single Unicode code point. Not to mention that when new emojis are introduced, there is a delay between iOS support and emoji release. That and the fact that different versions of iOS support different versions of the unicode standard.
TL;DR. I have worked on these features and opened sourced a library I am the author for JKEmoji to help parse strings with emojis. It makes parsing as easy as:
print("I love these emojis ?????????????".emojiCount)
5
It does that by routinely refreshing a local database of all recognized emojis as of the latest unicode version (12.0 as of recently) and cross-referencing them with what is recognized as a valid emoji in the running OS version by looking at the bitmap representation of an unrecognized emoji character.
NOTE
A previous answer got deleted for advertising my library without clearly stating that I am the author. I am acknowledging this again.
Solution 7:[7]
Try this code (actual for Swift 5):
extension Character {
var isSimpleEmoji: Bool {
guard let firstScalar = unicodeScalars.first else { return false }
return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
}
var isEmoji: Bool {
return isSimpleEmoji
}
}
extension String {
var emojis: [Character] { filter { $0.isEmoji } }
}
Use:
let emojisCount = yourString.emojis.count
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Meet Doshi |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | hstdt |
| Solution 5 | Arjen M |
| Solution 6 | |
| Solution 7 | VyacheslavBakinkskiy |
