Preciso descobrir se um caractere em uma string é um emoji.
Por exemplo, tenho este personagem:
let string = "😀"
let character = Array(string)[0]
Preciso descobrir se esse personagem é um emoji.
Preciso descobrir se um caractere em uma string é um emoji.
Por exemplo, tenho este personagem:
let string = "😀"
let character = Array(string)[0]
Preciso descobrir se esse personagem é um emoji.
let character = string[string.index(after: string.startIndex)]
ou let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Respostas:
O que descobri é a diferença entre caracteres, escalares Unicode e glifos.
Por exemplo, o glifo 👨👨👧👧 consiste em 7 escalares Unicode:
Outro exemplo, o glifo 👌🏿 consiste em 2 escalares Unicode:
Por último, o glifo 1️⃣ contém três caracteres Unicode:
Portanto, ao renderizar os caracteres, os glifos resultantes são realmente importantes.
O Swift 5.0 e superior tornam esse processo muito mais fácil e elimina algumas suposições que precisávamos fazer. Unicode.Scalar
é novoProperty
tipo de ajuda é determinar com o que estamos lidando. No entanto, essas propriedades só fazem sentido ao verificar os outros escalares dentro do glifo. É por isso que adicionaremos alguns métodos de conveniência à classe Character para nos ajudar.
Para obter mais detalhes, escrevi um artigo explicando como isso funciona .
Para Swift 5.0, ele deixa você com o seguinte resultado:
extension Character {
/// A simple emoji is one scalar and presented to the user as an Emoji
var isSimpleEmoji: Bool {
guard let firstScalar = unicodeScalars.first else { return false }
return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
}
/// Checks if the scalars will be merged into an emoji
var isCombinedIntoEmoji: Bool { unicodeScalars.count > 1 && unicodeScalars.first?.properties.isEmoji ?? false }
var isEmoji: Bool { isSimpleEmoji || isCombinedIntoEmoji }
}
extension String {
var isSingleEmoji: Bool { count == 1 && containsEmoji }
var containsEmoji: Bool { contains { $0.isEmoji } }
var containsOnlyEmoji: Bool { !isEmpty && !contains { !$0.isEmoji } }
var emojiString: String { emojis.map { String($0) }.reduce("", +) }
var emojis: [Character] { filter { $0.isEmoji } }
var emojiScalars: [UnicodeScalar] { filter { $0.isEmoji }.flatMap { $0.unicodeScalars } }
}
O que lhe dará os seguintes resultados:
"A̛͚̖".containsEmoji // false
"3".containsEmoji // false
"A̛͚̖▶️".unicodeScalars // [65, 795, 858, 790, 9654, 65039]
"A̛͚̖▶️".emojiScalars // [9654, 65039]
"3️⃣".isSingleEmoji // true
"3️⃣".emojiScalars // [51, 65039, 8419]
"👌🏿".isSingleEmoji // true
"🙎🏼♂️".isSingleEmoji // true
"🇹🇩".isSingleEmoji // true
"⏰".isSingleEmoji // true
"🌶".isSingleEmoji // true
"👨👩👧👧".isSingleEmoji // true
"🏴".isSingleEmoji // true
"🏴".containsOnlyEmoji // true
"👨👩👧👧".containsOnlyEmoji // true
"Hello 👨👩👧👧".containsOnlyEmoji // false
"Hello 👨👩👧👧".containsEmoji // true
"👫 Héllo 👨👩👧👧".emojiString // "👫👨👩👧👧"
"👨👩👧👧".count // 1
"👫 Héllœ 👨👩👧👧".emojiScalars // [128107, 128104, 8205, 128105, 8205, 128103, 8205, 128103]
"👫 Héllœ 👨👩👧👧".emojis // ["👫", "👨👩👧👧"]
"👫 Héllœ 👨👩👧👧".emojis.count // 2
"👫👨👩👧👧👨👨👦".isSingleEmoji // false
"👫👨👩👧👧👨👨👦".containsOnlyEmoji // true
Para versões mais antigas do Swift, verifique esta essência que contém meu código antigo.
containsOnlyEmoji
verificação. Eu também atualizei o exemplo para Swift 3.0.
A maneira mais simples, limpa e rápida de fazer isso é simplesmente verificar os pontos de código Unicode para cada caractere na string em relação aos intervalos de emoji e dingbats conhecidos, como:
extension String {
var containsEmoji: Bool {
for scalar in unicodeScalars {
switch scalar.value {
case 0x1F600...0x1F64F, // Emoticons
0x1F300...0x1F5FF, // Misc Symbols and Pictographs
0x1F680...0x1F6FF, // Transport and Map
0x2600...0x26FF, // Misc symbols
0x2700...0x27BF, // Dingbats
0xFE00...0xFE0F, // Variation Selectors
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
0x1F1E6...0x1F1FF: // Flags
return true
default:
continue
}
}
return false
}
}
0x1F900...0x1F9FF
(por Wikipedia). Não tenho certeza se todo o intervalo deve ser considerado emoji.
… Introduziu uma nova forma de verificar exatamente isso!
Você tem que quebrar o String
seu Scalars
. Cada Scalar
um tem um Property
valor que suporta o isEmoji
valor!
Na verdade, você pode até verificar se o escalar é um modificador de Emoji ou mais. Verifique a documentação da Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Você pode querer considerar verificar em isEmojiPresentation
vez de isEmoji
, porque a Apple afirma o seguinte para isEmoji
:
Esta propriedade é verdadeira para escalares que são renderizados como emoji por padrão e também para escalares que têm uma renderização de emoji não padrão quando seguido por U + FE0F VARIATION SELECTOR-16. Isso inclui alguns escalares que normalmente não são considerados emoji.
Dessa forma, na verdade, os Emojis são divididos em todos os modificadores, mas é mais simples de manusear. E como o Swift agora conta os Emoji com modificadores (por exemplo: 👨👩👧👦, 👨🏻💻, 🏴) como 1, você pode fazer todo o tipo de coisas.
var string = "🤓 test"
for scalar in string.unicodeScalars {
let isEmoji = scalar.properties.isEmoji
print("\(scalar.description) \(isEmoji)"))
}
// 🤓 true
// false
// t false
// e false
// s false
// t false
NSHipster aponta uma maneira interessante de obter todos os emojis:
import Foundation
var emoji = CharacterSet()
for codePoint in 0x0000...0x1F0000 {
guard let scalarValue = Unicode.Scalar(codePoint) else {
continue
}
// Implemented in Swift 5 (SE-0221)
// https://github.com/apple/swift-evolution/blob/master/proposals/0221-character-properties.md
if scalarValue.properties.isEmoji {
emoji.insert(scalarValue)
}
}
scalar.properties.isEmoji scalar.properties.isEmojiPresentation scalar.properties.isEmojiModifier scalar.properties.isEmojiModifierBase scalar.properties.isJoinControl scalar.properties.isVariationSelector
"6".unicodeScalars.first!.properties.isEmoji
vai avaliar comotrue
#
e *
que também retornarão verdadeiro para o isEmoji
cheque. isEmojiPresentation
parece funcionar melhor, pelo menos ele retorna false
para 0...9
, #
, *
e qualquer outro símbolo que eu poderia tentar em um teclado Inglês-US. Alguém tem mais experiência com ele e sabe se ele é confiável para validação de entrada?
extension String {
func containsEmoji() -> Bool {
for scalar in unicodeScalars {
switch scalar.value {
case 0x3030, 0x00AE, 0x00A9,// Special Characters
0x1D000...0x1F77F, // Emoticons
0x2100...0x27BF, // Misc symbols and Dingbats
0xFE00...0xFE0F, // Variation Selectors
0x1F900...0x1F9FF: // Supplemental Symbols and Pictographs
return true
default:
continue
}
}
return false
}
}
Esta é a minha correção, com intervalos atualizados.
Com o Swift 5 agora você pode inspecionar as propriedades unicode de cada caractere em sua string. Isso nos dá a isEmoji
variável conveniente em cada letra. O problema é isEmoji
que retornará verdadeiro para qualquer caractere que possa ser convertido em um emoji de 2 bytes, como 0-9.
Podemos olhar para a variável isEmoji
e também verificar a presença de um modificador de emoji para determinar se os caracteres ambíguos serão exibidos como um emoji.
Esta solução deve ser muito mais preparada para o futuro do que as soluções regex oferecidas aqui.
extension String {
func containsOnlyEmojis() -> Bool {
if count == 0 {
return false
}
for character in self {
if !character.isEmoji {
return false
}
}
return true
}
func containsEmoji() -> Bool {
for character in self {
if character.isEmoji {
return true
}
}
return false
}
}
extension Character {
// An emoji can either be a 2 byte unicode character or a normal UTF8 character with an emoji modifier
// appended as is the case with 3️⃣. 0x238C is the first instance of UTF16 emoji that requires no modifier.
// `isEmoji` will evaluate to true for any character that can be turned into an emoji by adding a modifier
// such as the digit "3". To avoid this we confirm that any character below 0x238C has an emoji modifier attached
var isEmoji: Bool {
guard let scalar = unicodeScalars.first else { return false }
return scalar.properties.isEmoji && (scalar.value > 0x238C || unicodeScalars.count > 1)
}
}
Dando-nos
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
enquantoCharacter("3").isEmoji // false
Swift 3 Nota:
Parece que o cnui_containsEmojiCharacters
método foi removido ou movido para uma biblioteca dinâmica diferente. _containsEmoji
ainda deve funcionar embora.
let str: NSString = "hello😊"
@objc protocol NSStringPrivate {
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, to: NSStringPrivate.self)
strPrivate._containsEmoji() // true
str.value(forKey: "_containsEmoji") // 1
let swiftStr = "hello😊"
(swiftStr as AnyObject).value(forKey: "_containsEmoji") // 1
Swift 2.x:
Recentemente, descobri uma API privada na NSString
qual expõe a funcionalidade para detectar se uma string contém um caractere Emoji:
let str: NSString = "hello😊"
Com um protocolo objc e unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
Com valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Com uma string Swift pura, você deve lançar a string como AnyObject
antes de usar valueForKey
:
let str = "hello😊"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
Métodos encontrados no arquivo de cabeçalho NSString .
Você pode usar este exemplo de código ou este pod .
Para usá-lo no Swift, importe a categoria para o YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Em seguida, você pode verificar o intervalo de cada emoji em sua String:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
Com o passar dos anos, essas soluções de detecção de emojis continuam surgindo à medida que a Apple adiciona novos emojis com novos métodos (como emojis em tons de pele criados por pré-amaldiçoar um personagem com um personagem adicional), etc.
Eu finalmente desisti e apenas escrevi o seguinte método que funciona para todos os emojis atuais e deve funcionar para todos os emojis futuros.
A solução cria um UILabel com o personagem e um fundo preto. CG então tira um instantâneo do rótulo e eu examino todos os pixels do instantâneo em busca de pixels não pretos sólidos. A razão pela qual adicionei o fundo preto é para evitar problemas de cores falsas devido à renderização de subpixel
A solução roda MUITO rápido no meu dispositivo, posso verificar centenas de caracteres por segundo, mas deve-se notar que esta é uma solução CoreGraphics e não deve ser usada pesadamente como você faria com um método de texto normal. O processamento de gráficos exige muitos dados, portanto, verificar milhares de caracteres de uma vez pode resultar em um atraso perceptível.
-(BOOL)isEmoji:(NSString *)character {
UILabel *characterRender = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
characterRender.text = character;
characterRender.font = [UIFont fontWithName:@"AppleColorEmoji" size:12.0f];//Note: Size 12 font is likely not crucial for this and the detector will probably still work at an even smaller font size, so if you needed to speed this checker up for serious performance you may test lowering this to a font size like 6.0
characterRender.backgroundColor = [UIColor blackColor];//needed to remove subpixel rendering colors
[characterRender sizeToFit];
CGRect rect = [characterRender bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef contextSnap = UIGraphicsGetCurrentContext();
[characterRender.layer renderInContext:contextSnap];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef imageRef = [capturedImage CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;//Note: Alpha Channel not really needed, if you need to speed this up for serious performance you can refactor this pixel scanner to just RGB
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
BOOL colorPixelFound = NO;
int x = 0;
int y = 0;
while (y < height && !colorPixelFound) {
while (x < width && !colorPixelFound) {
NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
CGFloat red = (CGFloat)rawData[byteIndex];
CGFloat green = (CGFloat)rawData[byteIndex+1];
CGFloat blue = (CGFloat)rawData[byteIndex+2];
CGFloat h, s, b, a;
UIColor *c = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
[c getHue:&h saturation:&s brightness:&b alpha:&a];//Note: I wrote this method years ago, can't remember why I check HSB instead of just checking r,g,b==0; Upon further review this step might not be needed, but I haven't tested to confirm yet.
b /= 255.0f;
if (b > 0) {
colorPixelFound = YES;
}
x++;
}
x=0;
y++;
}
return colorPixelFound;
}
AppleColorEmoji
, acrescentando que agora como um fail safe, embora eu ache que a Apple irá padronizá-la para essas de qualquer maneira
Para o Swift 3.0.2, a seguinte resposta é a mais simples:
class func stringContainsEmoji (string : NSString) -> Bool
{
var returnValue: Bool = false
string.enumerateSubstrings(in: NSMakeRange(0, (string as NSString).length), options: NSString.EnumerationOptions.byComposedCharacterSequences) { (substring, substringRange, enclosingRange, stop) -> () in
let objCString:NSString = NSString(string:substring!)
let hs: unichar = objCString.character(at: 0)
if 0xd800 <= hs && hs <= 0xdbff
{
if objCString.length > 1
{
let ls: unichar = objCString.character(at: 1)
let step1: Int = Int((hs - 0xd800) * 0x400)
let step2: Int = Int(ls - 0xdc00)
let uc: Int = Int(step1 + step2 + 0x10000)
if 0x1d000 <= uc && uc <= 0x1f77f
{
returnValue = true
}
}
}
else if objCString.length > 1
{
let ls: unichar = objCString.character(at: 1)
if ls == 0x20e3
{
returnValue = true
}
}
else
{
if 0x2100 <= hs && hs <= 0x27ff
{
returnValue = true
}
else if 0x2b05 <= hs && hs <= 0x2b07
{
returnValue = true
}
else if 0x2934 <= hs && hs <= 0x2935
{
returnValue = true
}
else if 0x3297 <= hs && hs <= 0x3299
{
returnValue = true
}
else if hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50
{
returnValue = true
}
}
}
return returnValue;
}
A resposta absolutamente semelhante àquelas que escrevi antes de mim, mas com um conjunto atualizado de escalares de emoji.
extension String {
func isContainEmoji() -> Bool {
let isContain = unicodeScalars.first(where: { $0.isEmoji }) != nil
return isContain
}
}
extension UnicodeScalar {
var isEmoji: Bool {
switch value {
case 0x1F600...0x1F64F,
0x1F300...0x1F5FF,
0x1F680...0x1F6FF,
0x1F1E6...0x1F1FF,
0x2600...0x26FF,
0x2700...0x27BF,
0xFE00...0xFE0F,
0x1F900...0x1F9FF,
65024...65039,
8400...8447,
9100...9300,
127000...127600:
return true
default:
return false
}
}
}
Você pode usar NSString-RemoveEmoji assim:
if string.isIncludingEmoji {
}
Existe uma boa solução para a tarefa mencionada. Mas verificar Unicode.Scalar.Properties de escalares Unicode é bom para um único caractere. E não é flexível o suficiente para Strings.
Podemos usar expressões regulares em vez - uma abordagem mais universal. Há uma descrição detalhada de como funciona abaixo. E aqui vai a solução.
No Swift, você pode verificar se uma String é um único caractere Emoji, usando uma extensão com tal propriedade computada:
extension String {
var isSingleEmoji : Bool {
if self.count == 1 {
let emodjiGlyphPattern = "\\p{RI}{2}|(\\p{Emoji}(\\p{EMod}|\\x{FE0F}\\x{20E3}?|[\\x{E0020}-\\x{E007E}]+\\x{E007F})|[\\p{Emoji}&&\\p{Other_symbol}])(\\x{200D}(\\p{Emoji}(\\p{EMod}|\\x{FE0F}\\x{20E3}?|[\\x{E0020}-\\x{E007E}]+\\x{E007F})|[\\p{Emoji}&&\\p{Other_symbol}]))*"
let fullRange = NSRange(location: 0, length: self.utf16.count)
if let regex = try? NSRegularExpression(pattern: emodjiGlyphPattern, options: .caseInsensitive) {
let regMatches = regex.matches(in: self, options: NSRegularExpression.MatchingOptions(), range: fullRange)
if regMatches.count > 0 {
// if any range found — it means, that that single character is emoji
return true
}
}
}
return false
}
}
Um único Emoji (um glifo) pode ser reproduzido por uma série de diferentes símbolos, sequências e suas combinações. Especificação Unicode define várias representações possíveis de caracteres Emoji.
Um caractere Emoji reproduzido por um único Unicode Scalar.
O Unicode define o caractere emoji como:
emoji_character := \p{Emoji}
Mas isso não significa necessariamente que tal personagem será desenhado como um Emoji. Um símbolo numérico comum “1” tem a propriedade Emoji sendo verdadeira, embora ainda possa ser desenhado como texto. E há uma lista de tais símbolos: #, ©, 4, etc.
Deve-se pensar que podemos usar uma propriedade adicional para verificar: “Emoji_Presentation”. Mas não funciona assim. Existe um Emoji como 🏟 ou 🛍, que tem a propriedade Emoji_Presentation = false.
Para ter certeza de que o personagem é desenhado como Emoji por padrão, devemos verificar sua categoria: deve ser “Other_symbol”.
Portanto, na verdade, a expressão regular para Emoji de um único caractere deve ser definida como:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Um personagem, que normalmente pode ser desenhado como texto ou como Emoji. Sua aparência depende de um símbolo especial seguinte, um seletor de apresentação, que indica o tipo de apresentação. \ x {FE0E} define a representação de texto. \ x {FE0F} define a representação de emoji.
A lista de tais símbolos pode ser encontrada [aqui] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
O Unicode define a sequência de apresentação como esta:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Sequência de expressão regular para ele:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
A sequência se parece muito com a sequência de apresentação, mas tem escalar adicional no final: \ x {20E3}. O escopo dos escalares de base possíveis usados para isso é bastante estreito: 0-9 # * - e isso é tudo. Exemplos: 1️⃣, 8️⃣, * ️⃣.
O Unicode define a sequência de teclas como esta:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Expressão regular para isso:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Alguns Emojis podem ter uma aparência modificada, como um tom de pele. Por exemplo, Emoji 🧑 pode ser diferente: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Para definir um Emoji, que é chamado de “Emoji_Modifier_Base” neste caso, pode-se usar um subsequente “Emoji_Modifier”.
Em geral, essa sequência tem a seguinte aparência:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Para detectá-lo, podemos pesquisar uma sequência de expressão regular:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
As bandeiras são emojis com sua estrutura particular. Cada bandeira é representada por dois símbolos “Regional_Indicator”.
Unicode os define como:
emoji_flag_sequence := regional_indicator regional_indicator
Por exemplo, bandeira da Ucrânia 🇺🇦 de fato é representada por dois escalares: \ u {0001F1FA \ u {0001F1E6}
Expressão regular para isso:
emoji_flag_sequence := \p{RI}{2}
Uma sequência que usa uma chamada tag_base, que é seguida por uma especificação de tag personalizada composta de um intervalo de símbolos \ x {E0020} - \ x {E007E} e concluída por tag_end mark \ x {E007F}.
Unicode o define assim:
emoji_tag_sequence := tag_base tag_spec tag_end
tag_base := emoji_character
| emoji_modifier_sequence
| emoji_presentation_sequence
tag_spec := [\x{E0020}-\x{E007E}]+
tag_end := \x{E007F}
O estranho é que o Unicode permite que a tag seja baseada em emoji_modifier_sequence ou emoji_presentation_sequence em ED-14a . Mas, ao mesmo tempo, em expressões regulares fornecidas na mesma documentação, eles parecem verificar a sequência com base em um único caractere Emoji.
Na lista de Emojis Unicode 12.1, existem apenas três desses Emojis definidos. Todas são bandeiras dos países do Reino Unido: Inglaterra 🏴, Escócia 🏴 e País de Gales 🏴. E todos eles são baseados em um único personagem Emoji. Portanto, é melhor verificarmos apenas essa sequência.
Expressão regular:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Um joiner de largura zero é um escalar \ x {200D}. Com sua ajuda, vários personagens, que já são Emojis por si só, podem ser combinados em novos.
Por exemplo, uma “família com pai, filho e filha” Emoji 👨👧👦 é reproduzida por uma combinação de Emojis pai 👨, filha 👧 e filho 👦 colados com símbolos ZWJ.
É permitido colar elementos, que são caracteres Emoji simples, sequências de apresentação e modificadores.
A expressão regular para tal sequência em geral se parece com isto:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Todas as representações de Emoji mencionadas acima podem ser descritas por uma única expressão regular:
\p{RI}{2}
| ( \p{Emoji}
( \p{EMod}
| \x{FE0F}\x{20E3}?
| [\x{E0020}-\x{E007E}]+\x{E007F}
)
|
[\p{Emoji}&&\p{Other_symbol}]
)
( \x{200D}
( \p{Emoji}
( \p{EMod}
| \x{FE0F}\x{20E3}?
| [\x{E0020}-\x{E007E}]+\x{E007F}
)
| [\p{Emoji}&&\p{Other_symbol}]
)
)*
Tive o mesmo problema e acabei fazendo um String
e Character
extensões.
O código é muito longo para postar, pois ele realmente lista todos os emojis (da lista unicode oficial v5.0) em um, CharacterSet
você pode encontrá-lo aqui:
https://github.com/piterwilson/StringEmoji
Conjunto de caracteres contendo todos os emojis conhecidos (conforme descrito na Lista Unicode 5.0 oficial http://unicode.org/emoji/charts-5.0/emoji-list.html )
Se a String
instância representa ou não um único caractere Emoji conhecido
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var containsEmoji: Bool {get}
Se a String
instância contém ou não um caractere Emoji conhecido
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Aplica um kCFStringTransformToUnicodeName
- CFStringTransform
em uma cópia da String
print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: String {get}
Retorna o resultado de a kCFStringTransformToUnicodeName
- CFStringTransform
com \N{
prefixos e }
sufixos removidos
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Se a Character
instância representa ou não um caractere Emoji conhecido
print("".isEmoji) // false
print("😁".isEmoji) // true