Ich muss herausfinden, ob ein Zeichen in einer Zeichenfolge ein Emoji ist.
Zum Beispiel habe ich diesen Charakter:
let string = "😀"
let character = Array(string)[0]
Ich muss herausfinden, ob dieser Charakter ein Emoji ist.
Ich muss herausfinden, ob ein Zeichen in einer Zeichenfolge ein Emoji ist.
Zum Beispiel habe ich diesen Charakter:
let string = "😀"
let character = Array(string)[0]
Ich muss herausfinden, ob dieser Charakter ein Emoji ist.
let character = string[string.index(after: string.startIndex)]
oder let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Antworten:
Worauf ich gestoßen bin, ist der Unterschied zwischen Zeichen, Unicode-Skalaren und Glyphen.
Zum Beispiel besteht die Glyphe 👨👨👧👧 aus 7 Unicode-Skalaren:
Ein weiteres Beispiel ist, dass die Glyphe 👌🏿 aus 2 Unicode-Skalaren besteht:
Zuletzt enthält die Glyphe 1️⃣ drei Unicode-Zeichen:
Beim Rendern der Zeichen sind die resultierenden Glyphen wirklich wichtig.
Swift 5.0 und höher vereinfacht diesen Prozess erheblich und beseitigt einige Vermutungen, die wir anstellen mussten. Unicode.Scalar
ist neuProperty
Typ hilft zu bestimmen, womit wir es zu tun haben. Diese Eigenschaften sind jedoch nur sinnvoll, wenn die anderen Skalare in der Glyphe überprüft werden. Aus diesem Grund werden wir der Character-Klasse einige praktische Methoden hinzufügen, um uns zu helfen.
Für weitere Details habe ich einen Artikel geschrieben, in dem erklärt wird, wie dies funktioniert .
Für Swift 5.0 erhalten Sie folgendes Ergebnis:
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 } }
}
Welches gibt Ihnen die folgenden Ergebnisse:
"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
Schauen Sie sich für ältere Swift-Versionen diese Liste an, die meinen alten Code enthält.
containsOnlyEmoji
Überprüfung geändert . Ich habe das Beispiel auch auf Swift 3.0 aktualisiert.
Der einfachste, sauberste und schnellste Weg, dies zu erreichen, besteht darin, einfach die Unicode-Codepunkte für jedes Zeichen in der Zeichenfolge mit bekannten Emo- und Dingbats-Bereichen zu vergleichen, wie z.
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). Nicht sicher, ob der gesamte Bereich als Emoji betrachtet werden sollte.
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
}
}
Dies ist mein Fix mit aktualisierten Bereichen.
… Eine neue Methode eingeführt, um genau dies zu überprüfen!
Sie müssen Ihre String
in seine brechen Scalars
. Jeder Scalar
hat einen Property
Wert, der das unterstütztisEmoji
Wert !
Sie können sogar überprüfen, ob der Skalar ein Emoji-Modifikator oder mehr ist. Lesen Sie die Dokumentation von Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Sie können für die Prüfung zu prüfen, isEmojiPresentation
statt isEmoji
, weil Apple die folgenden Zustände für isEmoji
:
Diese Eigenschaft gilt für Skalare, die standardmäßig als Emoji gerendert werden, sowie für Skalare, die ein nicht standardmäßiges Emoji-Rendering aufweisen, gefolgt von U + FE0F VARIATION SELECTOR-16. Dies schließt einige Skalare ein, die normalerweise nicht als Emoji betrachtet werden.
Auf diese Weise werden Emojis tatsächlich in alle Modifikatoren aufgeteilt, aber es ist viel einfacher zu handhaben. Und da Swift jetzt Emojis mit Modifikatoren (z. B. 👨👩👧👦, 👨🏻💻, 🏴) als 1 zählt, können Sie alle möglichen Dinge tun.
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 weist auf einen interessanten Weg hin, um alle Emojis zu bekommen:
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
wird bewertet alstrue
Mit Swift 5 können Sie jetzt die Unicode-Eigenschaften jedes Zeichens in Ihrer Zeichenfolge überprüfen. Dies gibt uns die bequeme isEmoji
Variable für jeden Buchstaben. Das Problem ist isEmoji
, dass true für jedes Zeichen zurückgegeben wird, das in ein 2-Byte-Emoji konvertiert werden kann, z. B. 0-9.
Wir können uns die Variable ansehen isEmoji
und auch prüfen, ob ein Emoji-Modifikator vorhanden ist, um festzustellen, ob die mehrdeutigen Zeichen als Emoji angezeigt werden.
Diese Lösung sollte viel zukunftssicherer sein als die hier angebotenen Regex-Lösungen.
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)
}
}
Geben uns
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
währendCharacter("3").isEmoji // false
Swift 3 Hinweis:
Es scheint, dass die cnui_containsEmojiCharacters
Methode entweder entfernt oder in eine andere dynamische Bibliothek verschoben wurde. _containsEmoji
sollte aber trotzdem funktionieren.
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:
Ich habe kürzlich eine private API entdeckt, auf NSString
der Funktionen zum Erkennen, ob eine Zeichenfolge ein Emoji-Zeichen enthält, verfügbar gemacht werden:
let str: NSString = "hello😊"
Mit einem Objektprotokoll und unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
Mit valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Bei einer reinen Swift-Saite müssen Sie die Saite wie AnyObject
folgt umwandeln valueForKey
:
let str = "hello😊"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
In der NSString-Headerdatei gefundene Methoden .
Sie können diesen Code verwenden Beispiel oder diese Schote .
Um es in Swift zu verwenden, importieren Sie die Kategorie in die YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Dann können Sie den Bereich für jedes Emoji in Ihrem String überprüfen:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
Ich habe ein kleines Beispielprojekt mit dem obigen Code erstellt.
Im Laufe der Jahre brechen diese Emoji-Erkennungslösungen immer wieder ab, da Apple neue Emojis mit neuen Methoden hinzufügt (wie hautfarbene Emojis, die durch Vorfluchen eines Zeichens mit einem zusätzlichen Zeichen erstellt wurden) usw.
Ich bin schließlich zusammengebrochen und habe gerade die folgende Methode geschrieben, die für alle aktuellen Emojis funktioniert und für alle zukünftigen Emojis funktionieren sollte.
Die Lösung erstellt ein UILabel mit dem Zeichen und einem schwarzen Hintergrund. CG macht dann einen Schnappschuss des Etiketts und ich scanne alle Pixel im Schnappschuss nach nicht durchgehend schwarzen Pixeln. Der Grund, warum ich den schwarzen Hintergrund hinzufüge, besteht darin, Probleme mit Falschfarben aufgrund von Subpixel-Rendering zu vermeiden
Die Lösung läuft auf meinem Gerät SEHR schnell, ich kann Hunderte von Zeichen pro Sekunde überprüfen, aber es sollte beachtet werden, dass dies eine CoreGraphics-Lösung ist und nicht so stark verwendet werden sollte, wie Sie es mit einer normalen Textmethode könnten. Die Grafikverarbeitung ist datenintensiv, sodass das gleichzeitige Überprüfen von Tausenden von Zeichen zu einer spürbaren Verzögerung führen kann.
-(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
, und fügt dies jetzt als ausfallsicher hinzu, obwohl ich denke, dass Apple es sowieso für diese festlegen wird
Für Swift 3.0.2 ist die folgende Antwort die einfachste:
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;
}
Die absolut ähnliche Antwort zu denen, die vor mir geschrieben haben, aber mit aktualisierten Emoji-Skalaren.
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
}
}
}
Sie können NSString-RemoveEmoji folgendermaßen verwenden :
if string.isIncludingEmoji {
}
Für die genannte Aufgabe gibt es eine gute Lösung . Das Überprüfen von Unicode.Scalar.Properties von Unicode-Skalaren ist jedoch für ein einzelnes Zeichen gut. Und nicht flexibel genug für Strings.
Wir können stattdessen reguläre Ausdrücke verwenden - universellerer Ansatz. Im Folgenden finden Sie eine detaillierte Beschreibung der Funktionsweise. Und hier geht die Lösung.
In Swift können Sie mithilfe einer Erweiterung mit einer solchen berechneten Eigenschaft überprüfen, ob ein String ein einzelnes Emoji-Zeichen ist:
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
}
}
Ein einzelnes Emoji (eine Glyphe) kann durch eine Reihe verschiedener Symbole, Sequenzen und deren Kombinationen reproduziert werden. Unicode-Spezifikation definiert mehrere mögliche Emoji-Zeichendarstellungen.
Ein Emoji-Zeichen, das von einem einzelnen Unicode-Skalar reproduziert wird.
Unicode definiert Emoji Character als:
emoji_character := \p{Emoji}
Dies bedeutet jedoch nicht unbedingt, dass ein solcher Charakter als Emoji gezeichnet wird. Bei einem gewöhnlichen numerischen Symbol „1“ ist die Emoji-Eigenschaft wahr, obwohl sie möglicherweise immer noch als Text gezeichnet wird. Und es gibt eine Liste solcher Symbole: #, ©, 4 usw.
Man sollte denken, dass wir zusätzliche Eigenschaften verwenden können, um zu überprüfen: "Emoji_Presentation". Aber so funktioniert es nicht. Es gibt ein Emoji wie 🏟 oder 🛍, die die Eigenschaft Emoji_Presentation = false haben.
Um sicherzustellen, dass das Zeichen standardmäßig als Emoji gezeichnet wird, sollten wir seine Kategorie überprüfen: Es sollte "Other_symbol" sein.
Tatsächlich sollte der reguläre Ausdruck für Emoji mit einem Zeichen wie folgt definiert werden:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Ein Zeichen, das normalerweise entweder als Text oder als Emoji gezeichnet werden kann. Das Erscheinungsbild hängt von einem speziellen folgenden Symbol ab, einem Präsentationswähler, der den Präsentationstyp angibt. \ x {FE0E} definiert die Textdarstellung. \ x {FE0F} definiert die Emoji-Darstellung.
Die Liste solcher Symbole finden Sie [hier] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
Unicode definiert die Präsentationssequenz wie folgt:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Reguläre Expressionssequenz dafür:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
Die Sequenz sieht der Präsentationssequenz sehr ähnlich, hat jedoch am Ende einen zusätzlichen Skalar: \ x {20E3}. Der Umfang der möglichen Basisskalare, die dafür verwendet werden, ist ziemlich eng: 0-9 # * - und das ist alles. Beispiele: 1️⃣, 8️⃣, * ️⃣.
Unicode definiert die Tastenkappenfolge wie folgt:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Regulärer Ausdruck dafür:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Einige Emojis können ein verändertes Aussehen wie ein Hautton haben. Zum Beispiel kann Emoji 🧑 anders sein: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Um ein Emoji zu definieren, das in diesem Fall "Emoji_Modifier_Base" heißt, kann ein nachfolgender "Emoji_Modifier" verwendet werden.
Im Allgemeinen sieht eine solche Sequenz folgendermaßen aus:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Um dies zu erkennen, können wir nach einer Sequenz mit regulären Ausdrücken suchen:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
Flaggen sind Emojis mit ihrer besonderen Struktur. Jedes Flag wird mit zwei Symbolen „Regional_Indicator“ dargestellt.
Unicode definiert sie wie folgt:
emoji_flag_sequence := regional_indicator regional_indicator
Zum Beispiel wird die Flagge der Ukraine 🇺🇦 tatsächlich mit zwei Skalaren dargestellt: \ u {0001F1FA \ u {0001F1E6}
Regulärer Ausdruck dafür:
emoji_flag_sequence := \p{RI}{2}
Eine Sequenz, die eine sogenannte tag_base verwendet, gefolgt von einer benutzerdefinierten Tag-Spezifikation, die aus einem Bereich von Symbolen \ x {E0020} - \ x {E007E} besteht und durch tag_end mark \ x {E007F} abgeschlossen wird.
Unicode definiert es folgendermaßen:
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}
Seltsamerweise erlaubt Unicode, dass das Tag in ED-14a auf emoji_modifier_sequence oder emoji_presentation_sequence basiert . Gleichzeitig scheinen sie in regulären Ausdrücken, die in derselben Dokumentation bereitgestellt werden , die Reihenfolge nur anhand eines einzelnen Emoji-Zeichens zu überprüfen.
In der Unicode 12.1 Emoji-Liste gibt es nur drei solcher Emojis definiert. Alle von ihnen sind Flaggen der britischen Länder: England, Schottland und Wales. Und alle basieren auf einem einzigen Emoji-Charakter. Wir sollten also nur nach einer solchen Sequenz suchen.
Regulären Ausdruck:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Ein Joiner mit einer Breite von Null ist ein Skalar \ x {200D}. Mit seiner Hilfe können mehrere Charaktere, die bereits Emojis sind, zu neuen kombiniert werden.
Zum Beispiel wird eine „Familie mit Vater, Sohn und Tochter“ Emoji 👨👧👦 durch eine Kombination von Vater 👨, Tochter 👧 und Sohn 👦 Emojis reproduziert, die mit ZWJ-Symbolen zusammengeklebt sind.
Es ist zulässig, Elemente zusammenzuhalten, bei denen es sich um einzelne Emoji-Zeichen, Präsentations- und Modifikatorsequenzen handelt.
Der reguläre Ausdruck für eine solche Sequenz sieht im Allgemeinen folgendermaßen aus:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Alle oben genannten Emoji-Darstellungen können durch einen einzigen regulären Ausdruck beschrieben werden:
\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}]
)
)*
Ich hatte das gleiche Problem und machte am Ende eine String
und Character
Erweiterungen.
Der Code ist zu lang, um ihn zu veröffentlichen, da er tatsächlich alle Emojis (aus der offiziellen Unicode-Liste v5.0) auflistet. CharacterSet
Sie finden ihn hier:
https://github.com/piterwilson/StringEmoji
Zeichensatz mit allen bekannten Emoji (wie in der offiziellen Unicode-Liste 5.0 beschrieben http://unicode.org/emoji/charts-5.0/emoji-list.html )
Gibt an, ob die String
Instanz ein bekanntes einzelnes Emoji-Zeichen darstellt
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var enthältEmoji: Bool {get}
Gibt an, ob die String
Instanz ein bekanntes Emoji-Zeichen enthält
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Wendet ein kCFStringTransformToUnicodeName
- CFStringTransform
auf eine Kopie des Strings an
print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: String {get}
Gibt das Ergebnis von a kCFStringTransformToUnicodeName
- zurück, CFStringTransform
wobei \N{
Präfixe und }
Suffixe entfernt wurden
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Gibt an, ob die Character
Instanz ein bekanntes Emoji-Zeichen darstellt
print("".isEmoji) // false
print("😁".isEmoji) // true