Necesito averiguar si un personaje de una cadena es un emoji.
Por ejemplo, tengo este personaje:
let string = "😀"
let character = Array(string)[0]
Necesito averiguar si ese personaje es un emoji.
Necesito averiguar si un personaje de una cadena es un emoji.
Por ejemplo, tengo este personaje:
let string = "😀"
let character = Array(string)[0]
Necesito averiguar si ese personaje es un emoji.
let character = string[string.index(after: string.startIndex)]
o let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Respuestas:
Lo que encontré es la diferencia entre caracteres, escalares Unicode y glifos.
Por ejemplo, el glifo 👨👨👧👧 consta de 7 escalares Unicode:
Otro ejemplo, el glifo 👌🏿 consta de 2 escalares Unicode:
El último, el glifo 1️⃣ contiene tres caracteres Unicode:
Entonces, al renderizar los caracteres, los glifos resultantes realmente importan.
Swift 5.0 y superior facilita mucho este proceso y elimina algunas conjeturas que teníamos que hacer. Unicode.Scalar
El nuevo Property
tipo ayuda a determinar a qué nos enfrentamos. Sin embargo, esas propiedades solo tienen sentido cuando se verifican los otros escalares dentro del glifo. Es por eso que agregaremos algunos métodos convenientes a la clase Character para ayudarnos.
Para obtener más detalles, escribí un artículo que explica cómo funciona esto .
Para Swift 5.0, te deja con el siguiente 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 } }
}
Lo que te dará los siguientes 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 versiones anteriores de Swift, consulte esta esencia que contiene mi código anterior.
containsOnlyEmoji
verificaciones. También actualicé el ejemplo a Swift 3.0.
La forma más simple, limpia y rápida de lograr esto es simplemente verificar los puntos de código Unicode para cada carácter en la cadena con rangos conocidos de emoji y dingbats, así:
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
(según Wikipedia). No estoy seguro de que todo el rango deba considerarse emoji.
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 es mi solución, con rangos actualizados.
... introdujo una nueva forma de comprobar exactamente esto.
Tienes que romper tu String
en su Scalars
. ¡Cada uno Scalar
tiene un Property
valor que respalda el isEmoji
valor!
De hecho, incluso puedes comprobar si el escalar es un modificador de Emoji o más. Consulte la documentación de Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Es posible que desee considerar la verificación en isEmojiPresentation
lugar de isEmoji
, porque Apple establece lo siguiente para isEmoji
:
Esta propiedad es válida para los escalares que se representan como emoji de forma predeterminada y también para los escalares que tienen una representación de emoji no predeterminada cuando son seguidos por U + FE0F VARIATION SELECTOR-16. Esto incluye algunos escalares que normalmente no se consideran emoji.
De esta manera, los Emoji se dividen en todos los modificadores, pero es mucho más sencillo de manejar. Y como Swift ahora cuenta los Emoji con modificadores (por ejemplo: 👨👩👧👦, 👨🏻💻, 🏴) como 1, puedes hacer todo tipo de cosas.
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 señala una forma interesante de obtener todos los Emoji:
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
se evaluará comotrue
Con Swift 5 ahora puede inspeccionar las propiedades Unicode de cada carácter en su cadena. Esto nos da la isEmoji
variable conveniente en cada letra. El problema es isEmoji
que devolverá verdadero para cualquier carácter que se pueda convertir en un emoji de 2 bytes, como 0-9.
Podemos mirar la variable isEmoji
y también verificar la presencia de un modificador de emoji para determinar si los caracteres ambiguos se mostrarán como un emoji.
Esta solución debería ser mucho más preparada para el futuro que las soluciones de expresiones regulares que se ofrecen aquí.
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)
}
}
Dándonos
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
mientrasCharacter("3").isEmoji // false
Swift 3 Nota:
Parece que el cnui_containsEmojiCharacters
método se eliminó o se movió a una biblioteca dinámica diferente. _containsEmoji
Sin embargo, aún debería funcionar.
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
Rápido 2.x:
Recientemente descubrí una API privada en la NSString
que expone la funcionalidad para detectar si una cadena contiene un carácter Emoji:
let str: NSString = "hello😊"
Con un protocolo objc y unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
Con valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Con una cuerda Swift pura, debes lanzar la cuerda 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 en el archivo de encabezado NSString .
Puede utilizar este ejemplo de código o este pod .
Para usarlo en Swift, importe la categoría en el YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Luego, puede verificar el rango de cada emoji en su Cadena:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
A lo largo de los años, estas soluciones de detección de emojis se siguen rompiendo a medida que Apple agrega nuevos emojis con nuevos métodos (como emojis con tonos de piel creados al maldecir previamente un personaje con un personaje adicional), etc.
Finalmente rompí y escribí el siguiente método que funciona para todos los emojis actuales y debería funcionar para todos los emojis futuros.
La solución crea una UILabel con el personaje y un fondo negro. CG luego toma una instantánea de la etiqueta y yo escaneo todos los píxeles en la instantánea en busca de píxeles que no sean negros sólidos. La razón por la que agrego el fondo negro es para evitar problemas de coloración falsa debido a representación de subpíxeles
La solución se ejecuta MUY rápido en mi dispositivo, puedo verificar cientos de caracteres por segundo, pero debe tenerse en cuenta que esta es una solución de CoreGraphics y no debe usarse mucho como lo haría con un método de texto normal. El procesamiento de gráficos tiene muchos datos, por lo que la verificación de miles de caracteres a la vez podría provocar un retraso notable.
-(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
, agregando que ahora es a prueba de fallas, aunque creo que Apple lo usará por defecto para esos de todos modos
Para Swift 3.0.2, la siguiente respuesta es la más simple:
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;
}
La respuesta absolutamente similar a las que escribieron antes que yo, pero con un conjunto actualizado de escalares 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
}
}
}
Puede usar NSString-RemoveEmoji así:
if string.isIncludingEmoji {
}
Existe una buena solución para la tarea mencionada. Pero comprobar Unicode.Scalar.Properties de escalares Unicode es bueno para un solo carácter. Y no lo suficientemente flexible para Strings.
Podemos usar expresiones regulares en su lugar , un enfoque más universal. Hay una descripción detallada de cómo funciona a continuación. Y aquí va la solución.
En Swift, puede verificar si una cadena es un solo carácter Emoji, usando una extensión con una propiedad calculada de este tipo:
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
}
}
Un solo Emoji (un glifo) se puede reproducir mediante varios símbolos, secuencias y combinaciones diferentes. Especificación Unicode define varias posibles representaciones de caracteres Emoji.
Un carácter Emoji reproducido por un único escalar Unicode.
Unicode define el carácter Emoji como:
emoji_character := \p{Emoji}
Pero no significa necesariamente que ese personaje se dibujará como un Emoji. Un símbolo numérico ordinario "1" tiene la propiedad Emoji siendo verdadera, aunque aún podría dibujarse como texto. Y hay una lista de tales símbolos: #, ©, 4, etc.
Uno debería pensar que podemos usar una propiedad adicional para verificar: “Emoji_Presentation”. Pero no funciona así. Hay un Emoji como 🏟 o 🛍, que tienen la propiedad Emoji_Presentation = false.
Para asegurarnos de que el personaje se dibuja como Emoji por defecto, debemos marcar su categoría: debe ser "Otro_símbolo".
Entonces, de hecho, la expresión regular para Emoji de un solo carácter debe definirse como:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Un personaje, que normalmente se puede dibujar como texto o como Emoji. Su apariencia depende de un siguiente símbolo especial, un selector de presentación, que indica su tipo de presentación. \ x {FE0E} define la representación del texto. \ x {FE0F} define la representación de emoji.
La lista de tales símbolos se puede encontrar [aquí] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
Unicode define la secuencia de presentación de esta manera:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Secuencia de expresión regular para ello:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
La secuencia se parece mucho a la secuencia de presentación, pero tiene un escalar adicional al final: \ x {20E3}. El alcance de los posibles escalares base utilizados para ello es bastante estrecho: 0-9 # * - y eso es todo. Ejemplos: 1️⃣, 8️⃣, * ️⃣.
Unicode define la secuencia de teclas de esta manera:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Expresión regular para ello:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Algunos emojis pueden tener una apariencia modificada, como un tono de piel. Por ejemplo, Emoji 🧑 puede ser diferente: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Para definir un Emoji, que se llama "Emoji_Modifier_Base" en este caso, se puede utilizar un "Emoji_Modifier" posterior.
En general, dicha secuencia se ve así:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Para detectarlo podemos buscar una secuencia de expresión regular:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
Las banderas son emojis con su estructura particular. Cada bandera está representada con dos símbolos “Regional_Indicator”.
Unicode los define como:
emoji_flag_sequence := regional_indicator regional_indicator
Por ejemplo, la bandera de Ucrania 🇺🇦 de hecho se representa con dos escalares: \ u {0001F1FA \ u {0001F1E6}
Expresión regular para ello:
emoji_flag_sequence := \p{RI}{2}
Una secuencia que utiliza la denominada base de etiquetas, que va seguida de una especificación de etiqueta personalizada compuesta por un rango de símbolos \ x {E0020} - \ x {E007E} y concluida por una marca de fin de etiqueta \ x {E007F}.
Unicode lo define así:
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}
Lo extraño es que Unicode permite que la etiqueta se base en emoji_modifier_sequence o emoji_presentation_sequence en ED-14a . Pero al mismo tiempo, en las expresiones regulares proporcionadas en la misma documentación , parecen verificar la secuencia basándose en un solo carácter Emoji.
En la lista de Emojis Unicode 12.1, solo hay tres de estos Emojis definidos. Todas ellas son banderas de los países del Reino Unido: Inglaterra 🏴, Escocia 🏴 y Gales 🏴. Y todos ellos se basan en un solo personaje Emoji. Entonces, será mejor que verifiquemos solo esa secuencia.
Expresión regular:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Un ensamblador de ancho cero es un escalar \ x {200D}. Con su ayuda, varios personajes, que ya son Emojis por sí mismos, se pueden combinar en otros nuevos.
Por ejemplo, un emoji 👨👧👦 de “familia con padre, hijo e hija” se reproduce mediante una combinación de emojis de padre 👨, hija 👧 e hijo 👦 pegados con símbolos ZWJ.
Se permite unir elementos, que son caracteres de un solo emoji, secuencias de presentación y modificadores.
La expresión regular para dicha secuencia en general se ve así:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Todas las representaciones de Emoji mencionadas anteriormente se pueden describir mediante una sola expresión 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}]
)
)*
Tuve el mismo problema y terminé haciendo extensiones String
y Character
.
El código es demasiado largo para publicarlo, ya que en realidad enumera todos los emojis (de la lista oficial de Unicode v5.0) en un CharacterSet
puedes encontrarlo aquí:
https://github.com/piterwilson/StringEmoji
Conjunto de caracteres que contiene todos los emoji conocidos (como se describe en la lista oficial Unicode 5.0 http://unicode.org/emoji/charts-5.0/emoji-list.html )
Si la String
instancia representa o no un único carácter emoji conocido
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var contieneEmoji: Bool {get}
Si la String
instancia contiene o no un carácter emoji conocido
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Aplica un kCFStringTransformToUnicodeName
- CFStringTransform
en una copia de la Cadena
print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: String {get}
Devuelve el resultado de a kCFStringTransformToUnicodeName
- CFStringTransform
con \N{
prefijos y }
sufijos eliminados
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Si la Character
instancia representa o no un carácter emoji conocido
print("".isEmoji) // false
print("😁".isEmoji) // true