Devo scoprire se un carattere in una stringa è un'emoji.
Ad esempio, ho questo personaggio:
let string = "😀"
let character = Array(string)[0]
Devo scoprire se quel personaggio è un'emoji.
Devo scoprire se un carattere in una stringa è un'emoji.
Ad esempio, ho questo personaggio:
let string = "😀"
let character = Array(string)[0]
Devo scoprire se quel personaggio è un'emoji.
let character = string[string.index(after: string.startIndex)]
o let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Risposte:
Quello in cui mi sono imbattuto è la differenza tra caratteri, scalari unicode e glifi.
Ad esempio, il glifo 👨👨👧👧 è composto da 7 scalari unicode:
Un altro esempio, il glifo 👌🏿 è costituito da 2 scalari unicode:
L'ultimo, il glifo 1️⃣ contiene tre caratteri Unicode:
Quindi, durante il rendering dei personaggi, i glifi risultanti contano davvero.
Swift 5.0 e versioni successive rendono questo processo molto più semplice e si liberano di alcune congetture che dovevamo fare. Unicode.Scalar
Il nuovo Property
tipo di aiuto è determinare con cosa abbiamo a che fare. Tuttavia, queste proprietà hanno senso solo quando si controllano gli altri scalari all'interno del glifo. Questo è il motivo per cui aggiungeremo alcuni metodi convenienti alla classe Character per aiutarci.
Per maggiori dettagli, ho scritto un articolo che spiega come funziona .
Per Swift 5.0, ti lascia con il seguente risultato:
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 } }
}
Che ti darà i seguenti risultati:
"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
Per le versioni precedenti di Swift, controlla questa sintesi contenente il mio vecchio codice.
containsOnlyEmoji
controlla. Ho anche aggiornato l'esempio a Swift 3.0.
Il modo più semplice, pulito e rapido per farlo è semplicemente controllare i punti di codice Unicode per ogni carattere nella stringa rispetto agli intervalli noti di emoji e dingbats, in questo modo:
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
(per Wikipedia). Non sono sicuro che tutta la gamma debba essere considerata emoji.
... ha introdotto un nuovo modo di controllare esattamente questo!
Bisogna rompere il vostro String
nel suo Scalars
. Ognuno Scalar
ha un Property
valore che supporta ilisEmoji
valore!
In realtà puoi anche verificare se lo scalare è un modificatore Emoji o più. Controlla la documentazione di Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Potresti prendere in considerazione il controllo isEmojiPresentation
invece di isEmoji
, perché Apple afferma quanto segue per isEmoji
:
Questa proprietà è vera per gli scalari che vengono visualizzati come emoji per impostazione predefinita e anche per gli scalari che hanno un rendering emoji non predefinito quando seguito da U + FE0F VARIATION SELECTOR-16. Ciò include alcuni scalari che non sono generalmente considerati emoji.
In questo modo in realtà divide le Emoji in tutti i modificatori, ma è molto più semplice da gestire. E poiché Swift ora conta gli Emoji con modificatori (ad esempio: 👨👩👧👦, 👨🏻💻, 🏴) come 1, puoi fare qualsiasi cosa.
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 indica un modo interessante per ottenere tutte le 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
valuterà cometrue
#
e *
anche questo restituirà vero per il isEmoji
controllo. isEmojiPresentation
sembra funzionare meglio, almeno restituisce false
per 0...9
, #
, *
e qualsiasi altro simbolo ho potuto provare su una tastiera inglese-statunitense. Qualcuno ha più esperienza con esso e sa se può essere considerato attendibile per la convalida dell'input?
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
}
}
Questa è la mia soluzione, con intervalli aggiornati.
Con Swift 5 ora puoi ispezionare le proprietà Unicode di ogni carattere nella tua stringa. Questo ci dà la comoda isEmoji
variabile su ogni lettera. Il problema èisEmoji
che restituirà vero per qualsiasi carattere che può essere convertito in un'emoji a 2 byte, come 0-9.
Possiamo guardare la variabile isEmoji
e anche verificare la presenza di un modificatore di emoji per determinare se i caratteri ambigui verranno visualizzati come emoji.
Questa soluzione dovrebbe essere molto più a prova di futuro rispetto alle soluzioni regex offerte qui.
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)
}
}
Dandoci
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
mentreCharacter("3").isEmoji // false
Swift 3 Nota:
Sembra che il cnui_containsEmojiCharacters
metodo sia stato rimosso o spostato in una libreria dinamica diversa. _containsEmoji
dovrebbe comunque funzionare.
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 ho scoperto un'API privata su NSString
cui espone funzionalità per rilevare se una stringa contiene un carattere Emoji:
let str: NSString = "hello😊"
Con un protocollo 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
Con valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Con una stringa Swift pura, devi lanciare la stringa come AnyObject
prima di utilizzare valueForKey
:
let str = "hello😊"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
Metodi trovati nel file di intestazione NSString .
Puoi usare questo esempio di codice o questo pod .
Per usarlo in Swift, importa la categoria nel file YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Quindi puoi controllare l'intervallo per ogni emoji nella tua stringa:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
Ho creato un piccolo progetto di esempio con il codice sopra.
Nel corso degli anni queste soluzioni di rilevamento di emoji continuano a rompersi mentre Apple aggiunge nuovi emoji con nuovi metodi (come gli emoji dai toni della pelle costruiti pre-maledicendo un personaggio con un carattere aggiuntivo), ecc.
Alla fine mi sono rotto e ho appena scritto il seguente metodo che funziona per tutti gli emoji attuali e dovrebbe funzionare per tutti gli emoji futuri.
La soluzione crea un'etichetta UIL con il personaggio e uno sfondo nero. CG quindi scatta un'istantanea dell'etichetta e io scannerizzo tutti i pixel nell'istantanea per eventuali pixel non neri. Il motivo per cui aggiungo lo sfondo nero è per evitare problemi di falsi colori dovuti a rendering dei pixel secondari
La soluzione funziona MOLTO velocemente sul mio dispositivo, posso controllare centinaia di caratteri al secondo, ma va notato che questa è una soluzione CoreGraphics e non dovrebbe essere utilizzata pesantemente come si potrebbe fare con un normale metodo di testo. L'elaborazione grafica è pesante per i dati, quindi il controllo di migliaia di caratteri contemporaneamente potrebbe comportare un notevole ritardo.
-(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
, aggiungendo che ora è un fail safe, anche se penso che Apple lo farà comunque di default per quelli
Per Swift 3.0.2, la seguente risposta è la più semplice:
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 risposta assolutamente simile a quelle che hanno scritto prima di me, ma con set aggiornato di scalari 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
}
}
}
Puoi usare NSString-RemoveEmoji in questo modo:
if string.isIncludingEmoji {
}
C'è una bella soluzione per il compito menzionato. Ma il controllo di Unicode.Scalar.Properties degli scalari unicode è buono per un singolo carattere. E non abbastanza flessibile per gli archi.
Possiamo invece usare le espressioni regolari - un approccio più universale. C'è una descrizione dettagliata di come funziona di seguito. E qui va la soluzione.
In Swift puoi verificare se una stringa è un singolo carattere Emoji, utilizzando un'estensione con una tale proprietà calcolata:
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 singolo Emoji (un glifo) può essere riprodotto da un numero di simboli, sequenze e loro combinazioni differenti. Specifica Unicode definisce diverse possibili rappresentazioni di caratteri Emoji.
Un carattere Emoji riprodotto da un singolo scalare Unicode.
Unicode definisce il carattere Emoji come:
emoji_character := \p{Emoji}
Ma non significa necessariamente che un personaggio del genere verrà disegnato come un'emoji. Un normale simbolo numerico "1" ha la proprietà Emoji che è vera, sebbene possa comunque essere disegnato come testo. E c'è un elenco di tali simboli: #, ©, 4, ecc.
Si dovrebbe pensare che possiamo usare proprietà aggiuntive per controllare: "Emoji_Presentation". Ma non funziona così. C'è un'emoji come 🏟 o 🛍, che ha la proprietà Emoji_Presentation = false.
Per essere sicuri che il personaggio sia disegnato come Emoji per impostazione predefinita, dovremmo controllare la sua categoria: dovrebbe essere "Other_symbol".
Quindi, in effetti, l'espressione regolare per Emoji a carattere singolo dovrebbe essere definita come:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Un personaggio, che normalmente può essere disegnato come testo o come Emoji. Il suo aspetto dipende da uno speciale simbolo seguente, un selettore di presentazione, che indica il tipo di presentazione. \ x {FE0E} definisce la rappresentazione del testo. \ x {FE0F} definisce la rappresentazione delle emoji.
L'elenco di tali simboli può essere trovato [qui] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
Unicode definisce la sequenza di presentazione in questo modo:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Sequenza di espressioni regolari per questo:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
La sequenza sembra molto simile alla sequenza di presentazione, ma ha uno scalare aggiuntivo alla fine: \ x {20E3}. L'ambito dei possibili scalari di base utilizzati è piuttosto ristretto: 0-9 # * - e questo è tutto. Esempi: 1️⃣, 8️⃣, * ️⃣.
Unicode definisce la sequenza di tasti in questo modo:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Espressione regolare per questo:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Alcuni Emoji possono avere un aspetto modificato come il tono della pelle. Ad esempio Emoji 🧑 può essere diverso: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Per definire un Emoji, che in questo caso si chiama “Emoji_Modifier_Base”, si può utilizzare un successivo “Emoji_Modifier”.
In generale tale sequenza è simile a questa:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Per rilevarlo possiamo cercare una sequenza di espressioni regolari:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
Le bandiere sono emoji con la loro particolare struttura. Ciascun flag è rappresentato con due simboli "Regional_Indicator".
Unicode li definisce come:
emoji_flag_sequence := regional_indicator regional_indicator
Ad esempio la bandiera dell'Ucraina 🇺🇦 infatti è rappresentata con due scalari: \ u {0001F1FA \ u {0001F1E6}
Espressione regolare per questo:
emoji_flag_sequence := \p{RI}{2}
Una sequenza che utilizza un cosiddetto tag_base, che è seguita da una specifica di tag personalizzata composta da un intervallo di simboli \ x {E0020} - \ x {E007E} e conclusa da tag_end mark \ x {E007F}.
Unicode lo definisce in questo modo:
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}
La cosa strana è che Unicode consente ai tag di essere basati su emoji_modifier_sequence o emoji_presentation_sequence in ED-14a . Ma allo stesso tempo nelle espressioni regolari fornite nella stessa documentazione sembrano controllare la sequenza basandosi solo su un singolo carattere Emoji.
Nell'elenco Emoji Unicode 12.1 ci sono solo tre di questi Emoji definiti. Sono tutte bandiere dei paesi del Regno Unito: Inghilterra 🏴, Scozia 🏴 e Galles 🏴. E tutti sono basati su un singolo personaggio Emoji. Quindi, faremmo meglio a controllare solo una sequenza del genere.
Espressione regolare:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Un joiner di larghezza zero è un \ x {200D} scalare. Con il suo aiuto diversi personaggi, che sono già Emoji da soli, possono essere combinati in nuovi.
Ad esempio, una "famiglia con padre, figlio e figlia" Emoji 👨👧👦 è riprodotta da una combinazione di emoji padre 👨, figlia 👧 e figlio 👦 incollati insieme ai simboli ZWJ.
È consentito unire elementi, che sono caratteri Emoji singoli, sequenze di presentazione e modificatori.
L'espressione regolare per tale sequenza in generale è simile a questa:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Tutte le rappresentazioni Emoji sopra menzionate possono essere descritte da una singola espressione regolare:
\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}]
)
)*
ho avuto lo stesso problema e ho finito per creare estensioni String
e Character
.
Il codice è troppo lungo per essere pubblicato poiché in realtà elenca tutti gli emoji (dall'elenco ufficiale Unicode v5.0) in un CharacterSet
che puoi trovare qui:
https://github.com/piterwilson/StringEmoji
Set di caratteri contenente tutte le emoji conosciute (come descritto in Unicode List 5.0 ufficiale http://unicode.org/emoji/charts-5.0/emoji-list.html )
Indica se l' String
istanza rappresenta o meno un singolo carattere Emoji noto
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var containsEmoji: Bool {get}
Indica se l' String
istanza contiene o meno un carattere Emoji noto
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Applica a kCFStringTransformToUnicodeName
- CFStringTransform
su una copia di 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}
Restituisce il risultato di un kCFStringTransformToUnicodeName
- CFStringTransform
con \N{
prefissi e }
suffissi rimossi
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Indica se l' Character
istanza rappresenta o meno un personaggio Emoji noto
print("".isEmoji) // false
print("😁".isEmoji) // true