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