J'ai besoin de savoir si un caractère dans une chaîne est un emoji.
Par exemple, j'ai ce caractère:
let string = "😀"
let character = Array(string)[0]
J'ai besoin de savoir si ce personnage est un emoji.
J'ai besoin de savoir si un caractère dans une chaîne est un emoji.
Par exemple, j'ai ce caractère:
let string = "😀"
let character = Array(string)[0]
J'ai besoin de savoir si ce personnage est un emoji.
let character = string[string.index(after: string.startIndex)]
ou let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Réponses:
Ce sur quoi je suis tombé, c'est la différence entre les caractères, les scalaires Unicode et les glyphes.
Par exemple, le glyphe 👨👨👧👧 se compose de 7 scalaires unicode:
Autre exemple, le glyphe 👌🏿 se compose de 2 scalaires unicode:
Le dernier, le glyphe 1️⃣ contient trois caractères unicode:
Ainsi, lors du rendu des caractères, les glyphes résultants comptent vraiment.
Swift 5.0 et supérieur rend ce processus beaucoup plus facile et élimine certaines hypothèses que nous devions faire. Unicode.Scalar
Le nouveau Property
type d 'aide est de déterminer à quoi nous avons affaire. Cependant, ces propriétés n'ont de sens que lors de la vérification des autres scalaires dans le glyphe. C'est pourquoi nous ajouterons des méthodes pratiques à la classe Character pour nous aider.
Pour plus de détails, j'ai écrit un article expliquant comment cela fonctionne .
Pour Swift 5.0, cela vous laisse le résultat suivant:
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 } }
}
Ce qui vous donnera les résultats suivants:
"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
Pour les anciennes versions de Swift, consultez cet essentiel contenant mon ancien code.
containsOnlyEmoji
contrôles. J'ai également mis à jour l'exemple vers Swift 3.0.
Le moyen le plus simple, le plus propre et le plus rapide d'y parvenir est de simplement vérifier les points de code Unicode pour chaque caractère de la chaîne par rapport aux plages d'emoji et de dingbats connues, comme ceci:
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
(par Wikipedia). Pas sûr que toute la gamme doive être considérée comme des 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
}
}
C'est ma solution, avec des plages mises à jour.
… Introduit une nouvelle façon de vérifier exactement cela!
Vous devez casser votre String
dans son Scalars
. Chacun Scalar
a une Property
valeur qui soutient la isEmoji
valeur!
En fait, vous pouvez même vérifier si le Scalar est un modificateur Emoji ou plus. Consultez la documentation d'Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Vous voudrez peut-être envisager de vérifier isEmojiPresentation
plutôt que isEmoji
, car Apple déclare ce qui suit pour isEmoji
:
Cette propriété est vraie pour les scalaires qui sont rendus sous forme d'emoji par défaut et également pour les scalaires qui ont un rendu d'emoji non par défaut lorsqu'ils sont suivis par U + FE0F VARIATION SELECTOR-16. Cela inclut certains scalaires qui ne sont généralement pas considérés comme des emoji.
De cette façon, les Emoji sont divisés en tous les modificateurs, mais c'est beaucoup plus simple à gérer. Et comme Swift compte désormais les Emoji avec des modificateurs (par exemple: 👨👩👧👦, 👨🏻💻, 🏴) comme 1, vous pouvez faire toutes sortes de choses.
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 souligne un moyen intéressant d'obtenir tous les 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
évaluera commetrue
Avec Swift 5, vous pouvez désormais inspecter les propriétés unicode de chaque caractère de votre chaîne. Cela nous donne la isEmoji
variable pratique sur chaque lettre. Le problème est isEmoji
qu'il renvoie vrai pour tout caractère qui peut être converti en un emoji de 2 octets, tel que 0-9.
Nous pouvons regarder la variable isEmoji
et également vérifier la présence d'un modificateur d'emoji pour déterminer si les caractères ambigus s'afficheront sous forme d'emoji.
Cette solution devrait être bien plus à l'épreuve du temps que les solutions regex proposées ici.
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)
}
}
Nous donnant
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
whileCharacter("3").isEmoji // false
Remarque sur Swift 3:
Il semble que la cnui_containsEmojiCharacters
méthode ait été supprimée ou déplacée vers une autre bibliothèque dynamique. _containsEmoji
devrait toujours fonctionner.
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:
J'ai récemment découvert une API privée sur NSString
laquelle expose des fonctionnalités pour détecter si une chaîne contient un caractère Emoji:
let str: NSString = "hello😊"
Avec un protocole objc et unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
Avec valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Avec une chaîne Swift pure, vous devez convertir la chaîne comme AnyObject
avant d'utiliser valueForKey
:
let str = "hello😊"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
Méthodes trouvées dans le fichier d'en-tête NSString .
Vous pouvez utiliser cet exemple de code ou ce pod .
Pour l'utiliser dans Swift, importez la catégorie dans le YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Ensuite, vous pouvez vérifier la plage de chaque emoji de votre chaîne:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
J'ai créé un petit exemple de projet avec le code ci-dessus.
Au fil des ans, ces solutions de détection des emojis continuent de se produire à mesure qu'Apple ajoute de nouveaux emojis avec de nouvelles méthodes (comme des emojis toniques de peau construits en pré-maudissant un personnage avec un caractère supplémentaire), etc.
Je suis finalement tombé en panne et j'ai juste écrit la méthode suivante qui fonctionne pour tous les emojis actuels et devrait fonctionner pour tous les futurs emojis.
La solution crée un UILabel avec le caractère et un fond noir. CG prend ensuite un instantané de l'étiquette et je scanne tous les pixels de l'instantané pour tout pixel non noir uni. La raison pour laquelle j'ajoute le fond noir est d'éviter les problèmes de fausse coloration dus au rendu de sous-pixels
La solution fonctionne TRÈS vite sur mon appareil, je peux vérifier des centaines de caractères par seconde, mais il convient de noter qu'il s'agit d'une solution CoreGraphics et ne doit pas être utilisée de manière intensive comme vous le feriez avec une méthode de texte ordinaire. Le traitement graphique est lourd en données, donc la vérification de milliers de caractères à la fois peut entraîner un retard 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
, ajoutant que maintenant comme une sécurité intégrée , bien que je pense qu'Apple le mettra par défaut pour ceux-là de toute façon
Pour Swift 3.0.2, la réponse suivante est la plus 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 réponse absolument similaire à celles qui ont écrit avant moi, mais avec un ensemble mis à jour de scalaires 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
}
}
}
Vous pouvez utiliser NSString-RemoveEmoji comme ceci:
if string.isIncludingEmoji {
}
Il existe une solution intéressante pour la tâche mentionnée. Mais vérifier les propriétés Unicode.Scalar.Properties des scalaires Unicode est bon pour un seul caractère. Et pas assez flexible pour les cordes.
Nous pouvons utiliser des expressions régulières à la place - approche plus universelle. Vous trouverez ci-dessous une description détaillée de son fonctionnement. Et voici la solution.
Dans Swift, vous pouvez vérifier si une chaîne est un seul caractère Emoji, en utilisant une extension avec une telle propriété calculée:
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 seul Emoji (un glyphe) peut être reproduit par un certain nombre de symboles, de séquences et de combinaisons différents. La spécification Unicode définit plusieurs représentations de caractères Emoji possibles.
Un personnage Emoji reproduit par un seul scalaire Unicode.
Unicode définit le caractère Emoji comme:
emoji_character := \p{Emoji}
Mais cela ne signifie pas nécessairement qu'un tel personnage sera dessiné comme un Emoji. Un symbole numérique ordinaire «1» a la propriété Emoji étant vrai, bien qu'il puisse toujours être dessiné sous forme de texte. Et il y a une liste de ces symboles: #, ©, 4, etc.
Il faut penser que nous pouvons utiliser une propriété supplémentaire pour vérifier: "Emoji_Presentation". Mais ça ne marche pas comme ça. Il existe un Emoji comme 🏟 ou 🛍, qui ont la propriété Emoji_Presentation = false.
Pour nous assurer que le personnage est dessiné comme Emoji par défaut, nous devons vérifier sa catégorie: il doit s'agir de «Other_symbol».
Donc, en fait, l'expression régulière pour Emoji à un seul caractère doit être définie comme:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Un caractère, qui peut normalement être dessiné sous forme de texte ou d'Emoji. Son apparence dépend d'un symbole spécial suivant, un sélecteur de présentation, qui indique son type de présentation. \ x {FE0E} définit la représentation textuelle. \ x {FE0F} définit la représentation emoji.
La liste de ces symboles peut être trouvée [ici] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
Unicode définit la séquence de présentation comme ceci:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Séquence d'expression régulière pour cela:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
La séquence ressemble beaucoup à la séquence de présentation, mais elle a un scalaire supplémentaire à la fin: \ x {20E3}. La portée des scalaires de base possibles utilisés pour cela est plutôt étroite: 0-9 # * - et c'est tout. Exemples: 1️⃣, 8️⃣, * ️⃣.
Unicode définit la séquence de touches comme ceci:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Expression régulière pour cela:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Certains Emojis peuvent avoir une apparence modifiée comme un teint. Par exemple, Emoji 🧑 peut être différent: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Pour définir un Emoji, qui est appelé "Emoji_Modifier_Base" dans ce cas, on peut utiliser un "Emoji_Modifier" ultérieur.
En général, une telle séquence ressemble à ceci:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Pour le détecter, nous pouvons rechercher une séquence d'expressions régulières:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
Les drapeaux sont des Emojis avec leur structure particulière. Chaque drapeau est représenté par deux symboles «Regional_Indicator».
Unicode les définit comme:
emoji_flag_sequence := regional_indicator regional_indicator
Par exemple, le drapeau de l'Ukraine 🇺🇦 est en fait représenté par deux scalaires: \ u {0001F1FA \ u {0001F1E6}
Expression régulière pour cela:
emoji_flag_sequence := \p{RI}{2}
Une séquence qui utilise ce que l'on appelle tag_base, qui est suivie d'une spécification de balise personnalisée composée d'une plage de symboles \ x {E0020} - \ x {E007E} et conclue par tag_end mark \ x {E007F}.
Unicode le définit comme ceci:
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}
Ce qui est étrange, c'est qu'Unicode permet aux balises d'être basées sur emoji_modifier_sequence ou emoji_presentation_sequence dans ED-14a . Mais en même temps, dans les expressions régulières fournies dans la même documentation, ils semblent vérifier la séquence basée sur un seul caractère Emoji.
Dans la liste Unicode 12.1 Emoji, seuls trois Emojis sont définis. Tous sont des drapeaux des pays du Royaume-Uni: l'Angleterre 🏴, l'Écosse 🏴 et le Pays de Galles 🏴. Et tous sont basés sur un seul personnage Emoji. Donc, nous ferions mieux de vérifier uniquement une telle séquence.
Expression régulière:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Un jointeur de largeur nulle est un scalaire \ x {200D}. Avec son aide, plusieurs personnages, qui sont déjà des Emojis par eux-mêmes, peuvent être combinés en de nouveaux.
Par exemple, une «famille avec père, fils et fille» Emoji 👨👧👦 est reproduite par une combinaison de père 👨, fille 👧 et fils 👦 Emojis collés avec les symboles ZWJ.
Il est permis de coller ensemble des éléments, qui sont des caractères Emoji uniques, des séquences de présentation et de modification.
L'expression régulière pour une telle séquence ressemble en général à ceci:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Toutes les représentations Emoji mentionnées ci-dessus peuvent être décrites par une seule expression régulière:
\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}]
)
)*
J'ai eu le même problème et j'ai fini par faire des extensions String
et Character
.
Le code est trop long à publier car il répertorie en fait tous les emojis (de la liste officielle Unicode v5.0) dans un, CharacterSet
vous pouvez le trouver ici:
https://github.com/piterwilson/StringEmoji
Jeu de caractères contenant tous les emoji connus (comme décrit dans la liste officielle Unicode 5.0 http://unicode.org/emoji/charts-5.0/emoji-list.html )
Si l' String
instance représente ou non un seul caractère Emoji connu
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var contientEmoji: Bool {get}
Si l' String
instance contient ou non un caractère Emoji connu
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Applique un kCFStringTransformToUnicodeName
- CFStringTransform
sur une copie de la chaîne
print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: String {get}
Renvoie le résultat d'un kCFStringTransformToUnicodeName
- CFStringTransform
avec les \N{
préfixes et }
suffixes supprimés
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Si l' Character
instance représente ou non un caractère Emoji connu
print("".isEmoji) // false
print("😁".isEmoji) // true