ios - Find out if Character in String is emoji? -
i need find out whether character in string emoji.
for example, have character:
let string = "😀" let character = array(string)[0]
i need find out if character emoji.
what stumbled upon difference between characters, unicode scalars , glyphs.
for example, glyph 👨👨👧👧 consists of 7 unicode scalars:
- four emoji characters: 👨👩👧👧
- in between each emoji special character, works character glue; see the specs more info
another example, glyph 👌🏿 consists of 2 unicode scalars:
- the regular emoji: 👌
- a skin tone modifier: 🏿
so when rendering characters, resulting glyphs matter.
what looking way detect if string , 1 emoji. render larger normal text (like messages on ios10 , whatsapp nowadays). described above, character count of no use. (the 'glue character' not considered emoji).
what can use coretext break down string glyphs , count them. furthermore, move part of extension proposed arnold , sebastian lopez separate extension of unicodescalar
.
it leaves following result:
import uikit extension unicodescalar { var isemoji: bool { switch value { case 0x1f600...0x1f64f, // emoticons 0x1f300...0x1f5ff, // misc symbols , pictographs 0x1f680...0x1f6ff, // transport , map 0x2600...0x26ff, // misc symbols 0x2700...0x27bf, // dingbats 0xfe00...0xfe0f, // variation selectors 0x1f900...0x1f9ff, // supplemental symbols , pictographs 65024...65039, // variation selector 8400...8447: // combining diacritical marks symbols return true default: return false } } var iszerowidthjoiner: bool { return value == 8205 } } 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 }) } // next tricks demonstrate how tricky can determine emoji's // if has suggestions how 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? 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? 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 } }
which give following results:
"👌🏿".issingleemoji // true "🙎🏼♂️".issingleemoji // true "👨👩👧👧".issingleemoji // true "👨👩👧👧".containsonlyemoji // true "hello 👨👩👧👧".containsonlyemoji // false "hello 👨👩👧👧".containsemoji // true "👫 héllo 👨👩👧👧".emojistring // "👫👨👩👧👧" "👨👩👧👧".glyphcount // 1 "👨👩👧👧".characters.count // 4 "👫 héllœ 👨👩👧👧".emojiscalars // [128107, 128104, 8205, 128105, 8205, 128103, 8205, 128103] "👫 héllœ 👨👩👧👧".emojis // ["👫", "👨👩👧👧"] "👫👨👩👧👧👨👨👦".issingleemoji // false "👫👨👩👧👧👨👨👦".containsonlyemoji // true "👫👨👩👧👧👨👨👦".glyphcount // 3 "👫👨👩👧👧👨👨👦".characters.count // 8
Comments
Post a Comment