Tôi cần tìm xem một ký tự trong chuỗi có phải là biểu tượng cảm xúc hay không.
Ví dụ, tôi có ký tự này:
let string = "😀"
let character = Array(string)[0]
Tôi cần tìm xem ký tự đó có phải là biểu tượng cảm xúc hay không.
Tôi cần tìm xem một ký tự trong chuỗi có phải là biểu tượng cảm xúc hay không.
Ví dụ, tôi có ký tự này:
let string = "😀"
let character = Array(string)[0]
Tôi cần tìm xem ký tự đó có phải là biểu tượng cảm xúc hay không.
let character = string[string.index(after: string.startIndex)]
hoặc let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
Câu trả lời:
Điều tôi vấp phải là sự khác biệt giữa các ký tự, vô hướng unicode và glyph.
Ví dụ, glyph 👨👨👧👧 bao gồm 7 vô hướng unicode:
Một ví dụ khác, glyph 👌🏿 bao gồm 2 vô hướng unicode:
Cuối cùng, glyph 1️⃣ chứa ba ký tự unicode:
Vì vậy, khi kết xuất các ký tự, glyphs kết quả thực sự quan trọng.
Swift 5.0 trở lên làm cho quá trình này dễ dàng hơn nhiều và loại bỏ một số phỏng đoán mà chúng tôi cần phải làm. Loại Unicode.Scalar
mới của Property
giúp xác định những gì chúng tôi đang giải quyết. Tuy nhiên, những thuộc tính đó chỉ có ý nghĩa khi kiểm tra các vô hướng khác trong glyph. Đây là lý do tại sao chúng tôi sẽ thêm một số phương thức tiện lợi vào lớp Character để giúp chúng tôi.
Để biết thêm chi tiết, tôi đã viết một bài báo giải thích cách hoạt động của điều này .
Đối với Swift 5.0, nó để lại cho bạn kết quả sau:
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 } }
}
Điều này sẽ cho bạn kết quả sau:
"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
Đối với các phiên bản Swift cũ hơn, hãy xem ý chính này chứa mã cũ của tôi.
containsOnlyEmoji
kiểm tra. Tôi cũng đã cập nhật ví dụ này lên Swift 3.0.
Cách đơn giản nhất, sạch nhất, và swiftiest cách để thực hiện điều này chỉ đơn giản là kiểm tra các điểm mã Unicode cho mỗi ký tự trong chuỗi chống lại được biết đến biểu tượng cảm xúc và dingbats phạm vi, như vậy:
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
(theo Wikipedia). Không chắc tất cả phạm vi đều được coi là biểu tượng cảm xúc.
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
}
}
Đây là bản sửa lỗi của tôi, với các phạm vi được cập nhật.
… Đã giới thiệu một cách mới để kiểm tra chính xác điều này!
Bạn phải đột nhập của bạn String
vào nó Scalars
. Mỗi Scalar
có một Property
giá trị hỗ trợ isEmoji
giá trị!
Trên thực tế, bạn thậm chí có thể kiểm tra xem Scalar có phải là công cụ sửa đổi Biểu tượng cảm xúc hay nhiều hơn. Kiểm tra tài liệu của Apple: https://developer.apple.com/documentation/swift/unicode/scalar/properties
Bạn có thể muốn xem xét kiểm tra isEmojiPresentation
thay vì isEmoji
, vì Apple tuyên bố như sau cho isEmoji
:
Thuộc tính này đúng cho các đại lượng vô hướng được hiển thị dưới dạng biểu tượng cảm xúc theo mặc định và cũng cho các đại diện vô hướng có hiển thị biểu tượng cảm xúc không mặc định khi được theo sau bởi U + FE0F VARIATION SELECTOR-16. Điều này bao gồm một số vô hướng thường không được coi là biểu tượng cảm xúc.
Cách này thực sự chia Biểu tượng cảm xúc thành tất cả các công cụ sửa đổi, nhưng cách xử lý đơn giản hơn. Và vì Swift hiện tính các Biểu tượng cảm xúc với các bổ ngữ (ví dụ: 👨👩👧👦, 👨🏻💻, 🏴) là 1, bạn có thể làm tất cả các loại.
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 chỉ ra một cách thú vị để lấy tất cả các Biểu tượng cảm xúc:
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
sẽ đánh giá làtrue
Với Swift 5, giờ đây bạn có thể kiểm tra các thuộc tính unicode của từng ký tự trong chuỗi của bạn. Điều này cung cấp cho chúng tôi isEmoji
biến thuận tiện trên mỗi chữ cái. Vấn đề là isEmoji
sẽ trả về true cho bất kỳ ký tự nào có thể được chuyển đổi thành biểu tượng cảm xúc 2 byte, chẳng hạn như 0-9.
Chúng tôi có thể xem xét biến isEmoji
và cũng kiểm tra sự hiện diện của công cụ sửa đổi biểu tượng cảm xúc để xác định xem các ký tự không rõ ràng có hiển thị dưới dạng biểu tượng cảm xúc hay không.
Giải pháp này sẽ là bằng chứng trong tương lai nhiều hơn so với các giải pháp regex được cung cấp ở đây.
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)
}
}
Cho chúng tôi
"hey".containsEmoji() //false
"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
Character("3️⃣").isEmoji // true
trong khiCharacter("3").isEmoji // false
Swift 3 Lưu ý:
Có vẻ như cnui_containsEmojiCharacters
phương thức đã bị xóa hoặc chuyển sang một thư viện động khác. _containsEmoji
vẫn nên làm việc mặc dù.
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:
Gần đây, tôi đã phát hiện ra một API riêng, trên NSString
đó có chức năng phát hiện xem một chuỗi có chứa ký tự Biểu tượng cảm xúc hay không:
let str: NSString = "hello😊"
Với một giao thức objc và unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
Với valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
Với một chuỗi Swift thuần túy, bạn phải ép kiểu chuỗi như AnyObject
trước khi sử dụng valueForKey
:
let str = "hello😊"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
Các phương thức được tìm thấy trong tệp tiêu đề NSString .
Bạn có thể sử dụng ví dụ mã này hoặc nhóm này .
Để sử dụng nó trong Swift, hãy nhập danh mục vào YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
Sau đó, bạn có thể kiểm tra phạm vi cho mọi biểu tượng cảm xúc trong Chuỗi của mình:
let example: NSString = "string👨👨👧👧with😍emojis✊🏿" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]
Trong những năm qua, các giải pháp phát hiện biểu tượng cảm xúc này tiếp tục bị phá vỡ khi Apple thêm các biểu tượng cảm xúc mới với các phương pháp mới (như biểu tượng cảm xúc có màu da được xây dựng bằng cách chửi trước một ký tự với một ký tự bổ sung), v.v.
Cuối cùng tôi đã phá vỡ và chỉ viết phương pháp sau đây phù hợp với tất cả các biểu tượng cảm xúc hiện tại và sẽ hoạt động cho tất cả các biểu tượng cảm xúc trong tương lai.
Giải pháp tạo một UILabel với ký tự và nền đen. Sau đó CG sẽ chụp nhanh nhãn và tôi quét tất cả các pixel trong ảnh chụp nhanh để tìm bất kỳ pixel nào không phải màu đen đặc. Lý do tôi thêm nền đen là để tránh các vấn đề về màu sai do Kết xuất Subpixel
Giải pháp chạy RẤT nhanh trên thiết bị của tôi, tôi có thể kiểm tra hàng trăm ký tự mỗi giây, nhưng cần lưu ý rằng đây là giải pháp CoreGraphics và không nên được sử dụng nhiều như bạn có thể làm với phương pháp văn bản thông thường. Xử lý đồ họa nặng dữ liệu nên việc kiểm tra hàng nghìn ký tự cùng lúc có thể dẫn đến độ trễ đáng chú ý.
-(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
, thêm rằng hiện tại là một sự cố an toàn, mặc dù tôi nghĩ Apple sẽ mặc định nó cho những điều đó
Đối với Swift 3.0.2, câu trả lời sau là câu trả lời đơn giản nhất:
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;
}
Câu trả lời hoàn toàn giống với những câu đã viết trước tôi, nhưng với bộ vô hướng biểu tượng cảm xúc được cập nhật.
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
}
}
}
Bạn có thể sử dụng NSString-RemoveEmoji như sau:
if string.isIncludingEmoji {
}
Có một giải pháp tốt cho nhiệm vụ được đề cập. Nhưng Kiểm tra Unicode.Scalar: Các đặc tính của vô hướng unicode là tốt cho một Ký tự duy nhất. Và không đủ linh hoạt cho Chuỗi.
Thay vào đó, chúng ta có thể sử dụng Biểu thức chính quy - cách tiếp cận phổ biến hơn. Có một mô tả chi tiết về cách nó hoạt động dưới đây. Và đây là giải pháp.
Trong Swift, bạn có thể kiểm tra xem một Chuỗi có phải là một ký tự Biểu tượng cảm xúc duy nhất hay không, bằng cách sử dụng tiện ích mở rộng có thuộc tính được tính toán như vậy:
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
}
}
Một biểu tượng cảm xúc (glyph) có thể được tái tạo bằng một số biểu tượng, trình tự và sự kết hợp của chúng. Đặc tả Unicode xác định một số biểu diễn ký tự Emoji có thể có.
Một ký tự Emoji được sao chép bởi một Scalar Unicode duy nhất.
Unicode định nghĩa Ký tự Biểu tượng cảm xúc là:
emoji_character := \p{Emoji}
Nhưng nó không nhất thiết có nghĩa là một nhân vật như vậy sẽ được vẽ dưới dạng Biểu tượng cảm xúc. Một ký hiệu số thông thường “1” có thuộc tính Biểu tượng cảm xúc là true, mặc dù nó vẫn có thể được vẽ dưới dạng văn bản. Và có một danh sách các ký hiệu như vậy: #, ©, 4, v.v.
Người ta nên nghĩ rằng chúng ta có thể sử dụng thuộc tính bổ sung để kiểm tra: “Emoji_Presentation”. Nhưng nó không hoạt động như thế này. Có một Biểu tượng cảm xúc như 🏟 hoặc 🛍, có thuộc tính Emoji_Presentation = false.
Để đảm bảo rằng ký tự được vẽ dưới dạng Biểu tượng cảm xúc theo mặc định, chúng ta nên kiểm tra danh mục của nó: nó phải là “Other_symbol”.
Vì vậy, trên thực tế, biểu thức chính quy cho Biểu tượng cảm xúc một ký tự phải được định nghĩa là:
emoji_character := \p{Emoji}&&\p{Other_symbol}
Một ký tự, thường có thể được vẽ dưới dạng văn bản hoặc dưới dạng Biểu tượng cảm xúc. Sự xuất hiện của nó phụ thuộc vào một ký hiệu đặc biệt sau, một bộ chọn bản trình bày, cho biết kiểu trình bày của nó. \ x {FE0E} xác định biểu diễn văn bản. \ x {FE0F} xác định biểu tượng cảm xúc.
Danh sách các biểu tượng như vậy có thể được tìm thấy [tại đây] ( https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt ).
Unicode định nghĩa trình tự trình bày như sau:
emoji_presentation_sequence := emoji_character emoji_presentation_selector
Chuỗi biểu thức chính quy cho nó:
emoji_presentation_sequence := \p{Emoji} \x{FE0F}
Trình tự trông rất giống với Trình tự trình bày, nhưng nó có thêm đại lượng vô hướng ở cuối: \ x {20E3}. Phạm vi của các đại lượng vô hướng cơ sở có thể được sử dụng cho nó khá hẹp: 0-9 # * - và đó là tất cả. Ví dụ: 1️⃣, 8️⃣, * ️⃣.
Unicode định nghĩa chuỗi keycap như sau:
emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}
Biểu thức chính quy cho nó:
emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}
Một số biểu tượng cảm xúc có thể có ngoại hình đã sửa đổi như màu da. Ví dụ Emoji 🧑 có thể khác: 🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿. Để xác định Biểu tượng cảm xúc, được gọi là “Emoji_Modifier_Base” trong trường hợp này, người ta có thể sử dụng một “Emoji_Modifier” tiếp theo.
Nói chung, trình tự như vậy trông như thế này:
emoji_modifier_sequence := emoji_modifier_base emoji_modifier
Để phát hiện nó, chúng ta có thể tìm kiếm một chuỗi biểu thức chính quy:
emoji_modifier_sequence := \p{Emoji} \p{EMod}
Cờ là biểu tượng cảm xúc với cấu trúc cụ thể của chúng. Mỗi lá cờ được biểu thị bằng hai biểu tượng “Regional_Indicator”.
Unicode định nghĩa chúng như sau:
emoji_flag_sequence := regional_indicator regional_indicator
Ví dụ: cờ của Ukraine 🇺🇦 trên thực tế được biểu thị bằng hai đại lượng vô hướng: \ u {0001F1FA \ u {0001F1E6}
Biểu thức chính quy cho nó:
emoji_flag_sequence := \p{RI}{2}
Một trình tự sử dụng cái gọi là tag_base, theo sau là một đặc điểm kỹ thuật thẻ tùy chỉnh được bao gồm từ dải ký hiệu \ x {E0020} - \ x {E007E} và được kết thúc bằng tag_end mark \ x {E007F}.
Unicode định nghĩa nó như thế này:
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}
Điều kỳ lạ là Unicode cho phép thẻ dựa trên emoji_modifier_sequence hoặc emoji_presentation_sequence trong ED-14a . Nhưng đồng thời trong các biểu thức chính quy được cung cấp cùng một tài liệu, chúng dường như chỉ kiểm tra trình tự dựa trên một ký tự Emoji duy nhất.
Trong danh sách Biểu tượng cảm xúc Unicode 12.1, chỉ có ba Biểu tượng cảm xúc như vậy được định nghĩa. Tất cả chúng đều là cờ của các nước thuộc Vương quốc Anh: England 🏴, Scotland 🏴 và Wales 🏴. Và tất cả chúng đều dựa trên một ký tự Emoji duy nhất. Vì vậy, chúng ta chỉ nên kiểm tra một trình tự như vậy.
Biểu hiện thông thường:
\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}
Bộ nối có độ rộng bằng 0 là một đại lượng vô hướng \ x {200D}. Với sự trợ giúp của nó, một số ký tự, vốn đã là Biểu tượng cảm xúc, có thể được kết hợp thành những ký tự mới.
Ví dụ: Biểu tượng cảm xúc “gia đình có cha, con trai và con gái” 👨👧👦 được tái tạo bằng sự kết hợp của cha 👨, con gái 👧 và con trai 👦 Biểu tượng cảm xúc được dán lại với nhau bằng các biểu tượng ZWJ.
Nó được phép gắn các yếu tố lại với nhau, đó là các ký tự Biểu tượng cảm xúc đơn, trình tự Trình bày và Trình tự sửa đổi.
Biểu thức chính quy cho chuỗi như vậy nói chung trông giống như sau:
emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+
Tất cả các biểu tượng Biểu tượng cảm xúc được đề cập ở trên có thể được mô tả bằng một biểu thức chính quy:
\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}]
)
)*
tôi đã gặp vấn đề tương tự và cuối cùng đã tạo ra một String
và Character
phần mở rộng.
Mã quá dài để đăng vì nó thực sự liệt kê tất cả các biểu tượng cảm xúc (từ danh sách unicode chính thức v5.0) trong một mã CharacterSet
bạn có thể tìm thấy tại đây:
https://github.com/piterwilson/StringEmoji
Bộ ký tự chứa tất cả các biểu tượng cảm xúc đã biết (như được mô tả trong Danh sách Unicode 5.0 chính thức http://unicode.org/emoji/charts-5.0/emoji-list.html )
Đối String
tượng có đại diện cho một ký tự Biểu tượng cảm xúc đã biết hay không
print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var chứaEmoji: Bool {get}
Đối tượng String
có chứa ký tự Biểu tượng cảm xúc đã biết hay không
print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var unicodeName: String {get}
Áp dụng a kCFStringTransformToUnicodeName
- CFStringTransform
trên bản sao của Chuỗi
print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: String {get}
Trả về kết quả của a kCFStringTransformToUnicodeName
- CFStringTransform
với \N{
các tiền tố và }
hậu tố bị xóa
print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
Đối Character
tượng có đại diện cho một ký tự Biểu tượng cảm xúc đã biết hay không
print("".isEmoji) // false
print("😁".isEmoji) // true