पता करें कि कैरेक्टर इन स्ट्रिंग इमोजी है?


92

मुझे यह पता लगाने की आवश्यकता है कि क्या एक स्ट्रिंग में एक चरित्र इमोजी है।

उदाहरण के लिए, मेरे पास यह चरित्र है:

let string = "😀"
let character = Array(string)[0]

मुझे यह पता लगाने की जरूरत है कि क्या वह चरित्र एक इमोजी है।


मैं उत्सुक हूं: आपको उस जानकारी की आवश्यकता क्यों है?
मार्टिन आर

@EricD: कई यूनिकोड वर्ण हैं जो एक से अधिक UTF-8 कोड बिंदु (जैसे "€" = E2 82 AC) या एक से अधिक UTF-16 कोड बिंदु (जैसे "𝄞" = D834 DD1E) लेते हैं।
मार्टिन आर

आशा है कि आपको इस obj-c संस्करण कोड stackoverflow.com/questions/19886642/…
आशीष कक्कड़

स्ट्रिंग्स में उनकी अनुक्रमण होती है जो उनका उपयोग करने का एक पसंदीदा तरीका है। एक विशेष चरित्र (या अंगूर के समूह के बजाय) पाने के लिए: आप कर सकते हैं: let character = string[string.index(after: string.startIndex)]या let secondCharacter = string[string.index(string.startIndex, offsetBy: 1)]
पॉल बी।

जवाबों:


239

क्या मैं ठोकर खाई चरित्र, यूनिकोड स्केलर और ग्लिफ़ के बीच अंतर है।

उदाहरण के लिए, ग्लिफ़ 👨👨👨 ,👧 of में 7 यूनिकोड स्केलर होते हैं:

एक और उदाहरण, ग्लिफ़ 👌🏿 में 2 यूनिकोड स्केल होते हैं:

  • नियमित इमोजी::
  • एक त्वचा टोन संशोधक::

अंतिम एक, ग्लिफ़ 1️⃣ में तीन यूनिकोड वर्ण हैं:

इसलिए जब पात्रों को प्रस्तुत करते हैं, तो परिणामी ग्लिफ़ वास्तव में मायने रखते हैं।

5.0 और ऊपर की स्विफ्ट इस प्रक्रिया को बहुत आसान बनाती है और हमें कुछ अनुमान लगाने से छुटकारा मिलता है जो हमें करने की आवश्यकता थी। Unicode.Scalarनए Propertyप्रकार की सहायता यह निर्धारित करती है कि हम किसके साथ काम कर रहे हैं। हालांकि, वे गुण केवल तभी समझ में आते हैं जब ग्लिफ़ के भीतर अन्य स्केलर की जाँच करते हैं। यही कारण है कि हम अपनी सहायता के लिए वर्ण वर्ग में कुछ सुविधा विधियाँ जोड़ रहे हैं।

अधिक विवरण के लिए, मैंने एक लेख लिखा जिसमें बताया गया है कि यह कैसे काम करता है

स्विफ्ट 5.0 के लिए, यह आपको निम्नलिखित परिणाम देता है:

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 } }
}

जो आपको निम्नलिखित परिणाम देगा:

"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

पुराने स्विफ्ट संस्करणों के लिए, मेरे पुराने कोड वाले इस जिस्ट की जांच करें।


6
यह अब तक का सबसे अच्छा और सबसे सही उत्तर है। धन्यवाद! एक छोटा सा नोट, आपके उदाहरण कोड से मेल नहीं खाते (आपने नाम बदला है।
टिम बुल

3
मेरा बुरा, मैं कुछ कोड के आसपास बदल गया, लगता है मैंने गड़बड़ कर दी। मैंने उदाहरण के लिए अपडेट किया
केविन आर

2
@Andrew: ज़रूर, मैंने इसे प्रदर्शित करने के लिए उदाहरण के लिए एक और तरीका जोड़ा :)।
केविन आर

2
@ और यह वह जगह है जहाँ यह वास्तव में गड़बड़ हो जाता है। मैंने एक उदाहरण जोड़ा कि कैसे करना है। समस्या यह है कि मुझे पता है कि कैसे CoreText बस पात्रों की जाँच करके ग्लिफ़ प्रस्तुत करेगा। अगर किसी के पास क्लीनर विधि के लिए सुझाव हैं तो कृपया मुझे बताएं।
केविन आर

3
@ और यह इंगित करने के लिए धन्यवाद, मैंने containsOnlyEmojiजांच के तरीके को बदल दिया है । मैंने Swift 3.0 का उदाहरण भी अपडेट किया।
केविन आर

51

सरल, साफ है, और swiftiest तरीका यह है, बस में जाना जाता इमोजी और dingbats पर्वतमाला, इसलिए तरह के खिलाफ स्ट्रिंग में हर किरदार के लिए यूनिकोड कोड अंक की जाँच करने के लिए है:

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
    }

}

9
इस तरह एक कोड उदाहरण तीसरे पक्ष के पुस्तकालय निर्भरता को शामिल करने के सुझाव से बेहतर है। शार्दुल के जवाब का पालन करने के लिए नासमझ सलाह है - हमेशा अपना कोड लिखें।
Thefaj

यह बहुत अच्छा है, आपको यह बताने के लिए धन्यवाद कि क्या मामले हैं
शॉन थ्रोप

2
आपके कोड की तरह, मैंने इसे एक उत्तर में यहां लागू किया । एक चीज जो मैंने देखी है कि यह कुछ इमोजी को याद करती है, हो सकता है कि वे आपके द्वारा सूचीबद्ध श्रेणियों का हिस्सा न हों, उदाहरण के लिए यह एक: रोबोट फेस इमोजी 🤖
क्यू

1
@ मुझे लगता है कि यह सीमा 0x1F900...0x1F9FF(प्रति विकिपीडिया) होगी। निश्चित रूप से सभी रेंज को इमोजी नहीं माना जाना चाहिए।
13

11

स्विफ्ट 5.0

... यह बिल्कुल जाँच का एक नया तरीका पेश किया!

आप अपने को तोड़ने के लिए है Stringअपने में Scalars। प्रत्येक Scalarका एक Propertyमान होता है जो मूल्य का समर्थन करता है isEmoji!

वास्तव में आप यह भी देख सकते हैं कि स्केलर एक इमोजी संशोधक है या अधिक। Apple के दस्तावेज़ीकरण देखें: https://developer.apple.com/documentation/swift/unicode/scalar/proferences

आप isEmojiPresentationइसके बदले जाँच करने पर विचार कर सकते हैं isEmoji, क्योंकि Apple निम्नलिखित के लिए बताता है isEmoji:

यह गुण स्केलर के लिए सही है, जिन्हें डिफ़ॉल्ट रूप से इमोजी के रूप में प्रस्तुत किया जाता है और उन स्केलरों के लिए भी है, जिनके पास U + FE0F संस्करण चयनकर्ता -16 के बाद गैर-डिफ़ॉल्ट इमोजी प्रतिपादन है। इसमें कुछ स्केल शामिल हैं जिन्हें आमतौर पर इमोजी नहीं माना जाता है।


यह तरीका वास्तव में इमोजी को सभी मॉडिफायर्स में विभाजित करता है, लेकिन इसे संभालना सरल है। और जैसा कि स्विफ्ट अब इमोजी को मॉडिफायर्स के साथ गिनता है (जैसे: 👩👩👩👧👦👦👦, 🏴🏴🏴, c) 1 के रूप में आप हर तरह का सामान कर सकते हैं।

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 ने सभी इमोजी को पाने के लिए एक दिलचस्प तरीका बताया:

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)
    }
}

1
शानदार जवाब, धन्यवाद। यह ध्यान देने योग्य है कि स्विफ्ट 5 के इस हिस्से का उपयोग करने के लिए आपका न्यूनतम एसडीके 10.2 होना चाहिए। यह जांचने के लिए कि क्या कोई स्ट्रिंग केवल एमोजिस से बनी है, मुझे यह जांचना था कि क्या इनमें से कोई एक गुण है:scalar.properties.isEmoji scalar.properties.isEmojiPresentation scalar.properties.isEmojiModifier scalar.properties.isEmojiModifierBase scalar.properties.isJoinControl scalar.properties.isVariationSelector
ए स्प्रिंगहम

6
खबरदार, पूर्णांक 0-9 को इमोजीस माना जाता है। तो के "6".unicodeScalars.first!.properties.isEmojiरूप में मूल्यांकन करेंगेtrue
लघु

1
जैसे अन्य चरित्र हैं #और *यह भी सच के लिए वापस आ जाएगीisEmoji चेक के । isEmojiPresentationबेहतर काम करने के लिए, कम से कम यह रिटर्न लगता है falseके लिए 0...9, #, *और किसी भी अन्य प्रतीक मैं एक अंग्रेजी अमेरिका कीबोर्ड पर कोशिश कर सकते। किसी को भी इसके साथ अधिक अनुभव है और जानता है कि क्या यह इनपुट सत्यापन के लिए विश्वसनीय हो सकता है?
Jan

8
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
    }
}

अपडेटेड रेंज के साथ यह मेरा फिक्स है।


7

स्विफ्ट 5 के साथ अब आप अपने स्ट्रिंग में प्रत्येक वर्ण के यूनिकोड गुणों का निरीक्षण कर सकते हैं। यह हमें isEmojiप्रत्येक अक्षर पर सुविधाजनक चर देता है। समस्या isEmojiकिसी भी वर्ण के लिए सही वापस आ जाएगी जिसे 2-बाइट वाली इमोजी में बदला जा सकता है, जैसे 0-9।

हम चर को देख सकते हैं isEmojiऔर यह भी निर्धारित करने के लिए एक इमोजी संशोधक की उपस्थिति की जांच कर सकते हैं कि अस्पष्ट अक्षर एक इमोजी के रूप में प्रदर्शित होंगे या नहीं।

यह समाधान यहां दिए गए रेगेक्स समाधानों की तुलना में अधिक भविष्य का प्रमाण होना चाहिए।

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)
    }
}

हमें देना

"hey".containsEmoji() //false

"Hello World 😎".containsEmoji() //true
"Hello World 😎".containsOnlyEmojis() //false

"3".containsEmoji() //false
"3️⃣".containsEmoji() //true

1
और क्या अधिक है Character("3️⃣").isEmoji // true, जबकिCharacter("3").isEmoji // false
पॉल बी

4

स्विफ्ट 3 नोट:

ऐसा लगता है कि cnui_containsEmojiCharactersविधि को या तो हटा दिया गया है या एक अलग गतिशील पुस्तकालय में ले जाया गया है। _containsEmojiहालांकि अभी भी काम करना चाहिए।

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

स्विफ्ट 2.x:

मैंने हाल ही में एक निजी एपीआई की खोज की है, NSStringजिस पर यह पता लगाने के लिए कार्यक्षमता उजागर होती है कि क्या एक स्ट्रिंग में इमोजी वर्ण है:

let str: NSString = "hello😊"

एक objc प्रोटोकॉल के साथ और unsafeBitCast:

@objc protocol NSStringPrivate {
    func cnui_containsEmojiCharacters() -> ObjCBool
    func _containsEmoji() -> ObjCBool
}

let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true

के साथ valueForKey:

str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1

शुद्ध स्विफ्ट स्ट्रिंग के साथ, आपको AnyObjectउपयोग करने से पहले स्ट्रिंग डाली जानी चाहिए valueForKey:

let str = "hello😊"

(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1

NSString हेडर फ़ाइल में पाए गए तरीके ।


यह वही है जो मैं देख रहा हूँ, धन्यवाद JAL

क्या यह Apple द्वारा खारिज कर दिया जाएगा?
एंड्री चेर्नुखा

@AndreyChernukha वहाँ हमेशा एक जोखिम है, लेकिन मैंने अभी तक किसी भी अस्वीकृति का अनुभव नहीं किया है।
JAL

कभी भी निजी APIs का उपयोग न करें। सबसे अच्छा, चोट केवल कल ही आएगी। या अगले महीने।
xaphod

3

आप इस कोड उदाहरण या इस पॉड का उपयोग कर सकते हैं ।

स्विफ्ट में इसका उपयोग करने के लिए, श्रेणी में आयात करें YourProject_Bridging_Header

#import "NSString+EMOEmoji.h"

फिर आप अपने स्ट्रिंग में प्रत्येक इमोजी के लिए सीमा की जांच कर सकते हैं:

let example: NSString = "string👨‍👨‍👧‍👧with😍emojis✊🏿" //string with emojis

let containsEmoji: Bool = example.emo_containsEmoji()

    print(containsEmoji)

// Output: ["true"]

मैंने ऊपर दिए कोड के साथ एक छोटा सा उदाहरण प्रोजेक्ट बनाया।


3

भविष्य के प्रमाण: मैन्युअल रूप से चरित्र के पिक्सेल की जाँच करें; नए इमोजीस जोड़े जाने के साथ अन्य समाधान टूटेंगे (और टूट गए हैं)।

नोट: यह ऑब्जेक्टिव-सी है (इसे स्विफ्ट में बदला जा सकता है)

इन वर्षों में ये इमोजी-डिटेक्टिंग सॉल्यूशंस टूटते रहते हैं क्योंकि Apple नए इमोजीस w / नए तरीके जोड़ता है (जैसे स्किन-टोन्ड इमोजीस को एक अतिरिक्त कैरेक्टर वाले कैरेक्टर को कोसते हुए बनाया जाता है), आदि।

मैं अंत में टूट गया और बस निम्नलिखित विधि लिखी जो सभी वर्तमान इमोजीस के लिए काम करती है और भविष्य के सभी इमोजीस के लिए काम करना चाहिए।

समाधान चरित्र और एक काले रंग की पृष्ठभूमि के साथ एक UILabel बनाता है। CG फिर लेबल का एक स्नैपशॉट लेता है और मैं किसी भी ठोस-काले पिक्सेल के लिए स्नैपशॉट में सभी पिक्सेल स्कैन करता हूँ। ब्लैक बैक जोड़ने का कारण यह है कि सबपिक्सल रेंडरिंग के कारण झूठे रंग के मुद्दों से बचा जा सकता है

समाधान मेरे डिवाइस पर बहुत तेजी से चलता है, मैं सैकड़ों वर्णों को एक सेकंड में जांच सकता हूं, लेकिन यह ध्यान दिया जाना चाहिए कि यह एक कोरग्राफिक्स समाधान है और इसका उपयोग भारी रूप से नहीं किया जाना चाहिए जैसे आप एक नियमित पाठ विधि के साथ कर सकते हैं। ग्राफिक्स प्रोसेसिंग डेटा भारी है इसलिए एक बार में हजारों पात्रों की जांच करने से ध्यान देने योग्य अंतराल हो सकता है।

-(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;
    
}

5
मै आपकी सोच को पसंद करता हूं! ;) - अलग सोच!
रेमन

आप हमारे साथ ऐसा क्यों कर रहे हैं? #apple #unicodestandard 😱🤔🤪🙈😈🤕💩
d4Rk

मैंने थोड़ी देर में इस पर ध्यान नहीं दिया लेकिन मुझे आश्चर्य है कि अगर मुझे UIColor में बदलना है तो hsb में; ऐसा लगता है कि मैं बस उस आर, जी, बी सभी == 0 की जांच कर सकता हूं? अगर कोई मुझे बताने की कोशिश करता है
अल्बर्ट रेनशॉ

मुझे यह समाधान पसंद है, लेकिन क्या यह this जैसे चरित्र के साथ नहीं टूटेगा?
जुआन कार्लोस ओस्पिना गोंजालेज

1
@JuanCarlosOspinaGonzalez नोप, इमोजी में जो एक सफेद के साथ एक नीले बॉक्स के रूप में प्रस्तुत करता है। यह एक अच्छा बिंदु लाता है, हालांकि कि उइबेल को फ़ॉन्ट को मजबूर करना चाहिए AppleColorEmoji, जो कि अब एक सुरक्षित सुरक्षित के रूप में जोड़ रहा है, हालांकि मुझे लगता है कि Apple इसे वैसे भी के लिए डिफ़ॉल्ट करेगा
अल्बर्ट रेनशॉ

2

स्विफ्ट 3.0.2 के लिए, निम्नलिखित उत्तर सबसे सरल है:

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;
}

2

उन लोगों के लिए बिल्कुल वैसा ही जवाब जो मेरे सामने लिखा था, लेकिन इमोजी स्केलर्स के अपडेटेड सेट के साथ।

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
        }
    }

}


1

उल्लेखित कार्य के लिए एक अच्छा समाधान है । लेकिन Unicode.Scalar की जाँच करना। यूनिकोड स्केलर्स की जाँच एक एकल वर्ण के लिए अच्छा है। और स्ट्रिंग्स के लिए पर्याप्त लचीला नहीं है।

हम इसके बजाय नियमित एक्सप्रेशन का उपयोग कर सकते हैं - अधिक सार्वभौमिक दृष्टिकोण। नीचे यह कैसे काम करता है, इसका विस्तृत विवरण है। और यहाँ समाधान हो जाता है।

समाधान

स्विफ्ट में आप जांच सकते हैं कि क्या स्ट्रिंग एक एकल इमोजी चरित्र है, जो इस तरह की गणना की गई संपत्ति के साथ एक्सटेंशन का उपयोग कर रहा है:

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
    }

}

यह कैसे काम करता है (विवरण में)

एक एकल इमोजी (एक ग्लिफ़) को कई विभिन्न प्रतीकों, अनुक्रमों और उनके संयोजनों द्वारा पुन: प्रस्तुत किया जा सकता है। यूनिकोड विनिर्देशन कई संभावित इमोजी चरित्र अभ्यावेदन को परिभाषित करता है।

सिंगल-कैरेक्टर इमोजी

एक इमोजी चरित्र एक एकल यूनिकोड स्केलर द्वारा पुन: पेश किया गया।

यूनिकोड के रूप में इमोजी चरित्र को परिभाषित करता है:

emoji_character := \p{Emoji}

लेकिन यह जरूरी नहीं है कि इस तरह के चरित्र को इमोजी के रूप में तैयार किया जाएगा। एक साधारण सांख्यिक प्रतीक "1" में इमोजी संपत्ति सच है, हालांकि यह अभी भी पाठ के रूप में तैयार किया जा सकता है। और ऐसे प्रतीकों की एक सूची है: #, ©, 4, आदि।

किसी को यह सोचना चाहिए, कि हम जाँच करने के लिए अतिरिक्त संपत्ति का उपयोग कर सकते हैं: "Emoji_Presentation"। लेकिन यह इस तरह काम नहीं करता है। 🏟 या 🏟 की तरह एक इमोजी है, जिसमें संपत्ति Emoji_Presentation = false है।

यह सुनिश्चित करने के लिए कि चरित्र को डिफ़ॉल्ट रूप से इमोजी के रूप में तैयार किया गया है, हमें इसकी श्रेणी की जांच करनी चाहिए: यह "अन्य_समूह" होना चाहिए।

इसलिए, वास्तव में सिंगल-कैरेक्टर इमोजी के लिए नियमित अभिव्यक्ति को इस प्रकार परिभाषित किया जाना चाहिए:

emoji_character := \p{Emoji}&&\p{Other_symbol}

इमोजी प्रस्तुति अनुक्रम

एक चरित्र, जिसे आम तौर पर या तो पाठ के रूप में या इमोजी के रूप में तैयार किया जा सकता है। यह उपस्थिति एक विशेष निम्नलिखित प्रतीक पर निर्भर करता है, एक प्रस्तुति चयनकर्ता, जो इसकी प्रस्तुति प्रकार को इंगित करता है। \ x {FE0E} पाठ प्रतिनिधित्व को परिभाषित करता है। \ x {FE0F} इमोजी प्रतिनिधित्व को परिभाषित करता है।

ऐसे प्रतीकों की सूची [यहाँ] (
 https://unicode.org/Public/emoji/12.1/emoji-variation-fterences.txt ) से प्राप्त की जा सकती है।

यूनिकोड इस तरह प्रस्तुति अनुक्रम को परिभाषित करता है:

emoji_presentation_sequence := emoji_character emoji_presentation_selector

इसके लिए नियमित अभिव्यक्ति क्रम:

emoji_presentation_sequence := \p{Emoji} \x{FE0F}

इमोजी कीप सीक्वेंस

प्रेजेंटेशन सीक्वेंस के साथ सीक्वेंस एक जैसे लगते हैं, लेकिन इसमें अंत में अतिरिक्त स्केलर है: \ x {20E3}। इसके लिए उपयोग किए जाने वाले संभावित आधार स्केल का दायरा संकीर्ण है: 0-9 # * - और यह सब है। उदाहरण: 1️⃣, 8️⃣, * ️⃣।

यूनिकोड इस तरह के कीप अनुक्रम को परिभाषित करता है:

emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}

इसके लिए नियमित अभिव्यक्ति:

emoji_keycap_sequence := \p{Emoji} \x{FE0F} \x{FE0F}

इमोजी संशोधक अनुक्रम

कुछ Emojis में स्किन टोन जैसा संशोधित रूप हो सकता है। उदाहरण के लिए इमोजी: अलग हो सकते हैं: 🧑। एक इमोजी को परिभाषित करने के लिए, जिसे इस मामले में "Emoji_Modifier_Base" कहा जाता है, कोई बाद में "Emoji_Modifier" का उपयोग कर सकता है।

सामान्य तौर पर ऐसा क्रम इस तरह दिखता है:

emoji_modifier_sequence := emoji_modifier_base emoji_modifier

इसका पता लगाने के लिए हम एक नियमित अभिव्यक्ति अनुक्रम की खोज कर सकते हैं:

emoji_modifier_sequence := \p{Emoji} \p{EMod}

इमोजी फ्लैग सीक्वेंस

झंडे अपनी विशेष संरचना के साथ एमोजिस हैं। प्रत्येक ध्वज को दो "Regional_Indicator" प्रतीकों के साथ दर्शाया गया है।

यूनिकोड उन्हें परिभाषित करता है:

emoji_flag_sequence := regional_indicator regional_indicator

उदाहरण के लिए यूक्रेन का झंडा 🇺🇦 वास्तव में दो स्केलों के साथ प्रदर्शित होता है: \ u {0001F1FA \ u {0001F1.16}

इसके लिए नियमित अभिव्यक्ति:

emoji_flag_sequence := \p{RI}{2}

इमोजी टैग अनुक्रम (ETS)

एक अनुक्रम जो एक तथाकथित tag_base का उपयोग करता है, जो एक कस्टम टैग विनिर्देश द्वारा प्रतीक \ x {E0020} - \ x {E007E} की सीमा से बना है और tag_end mark \ x {E007E} द्वारा निष्कर्ष निकाला है।

यूनिकोड इसे इस तरह परिभाषित करता है:

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}

अजीब बात यह है कि ईडी -14 में यूनिकोड टैग को इमोजी_मोडिफायर_ परिणाम या इमोजी_प्रस्तुति_ परिणाम के आधार पर अनुमति देता है । लेकिन एक ही प्रलेखन में प्रदान किए गए नियमित अभिव्यक्तियों में एक ही समय में वे केवल एक इमोजी चरित्र के आधार पर अनुक्रम की जांच करते दिखते हैं।

यूनिकोड 12.1 इमोजी सूची में केवल तीन ऐसे इमोजी हैं परिभाषित किया गया है। ये सभी यूके के देशों के झंडे हैं: इंग्लैंड of, स्कॉटलैंड of और वेल्स of। और ये सभी एक ही इमोजी कैरेक्टर पर आधारित हैं। इसलिए, हम केवल इस तरह के अनुक्रम के लिए बेहतर जाँच करेंगे।

नियमित अभिव्यक्ति:

\p{Emoji} [\x{E0020}-\x{E007E}]+ \x{E007F}

इमोजी शून्य-चौड़ाई योजक अनुक्रम (ZWJ अनुक्रम)

एक शून्य-चौड़ाई जॉइनर एक स्केलर \ x {200 डी} है। इसकी मदद से कई पात्र, जो पहले से ही Emojis हैं, को नए में जोड़ा जा सकता है।

एक उदाहरण के लिए "पिता, पुत्र और पुत्री के साथ परिवार" इमोजी 👧👦👦W को ZWJ प्रतीकों के साथ मिलकर son, बेटी 👧 और बेटे oj Emojis के संयोजन से दोबारा बनाया गया है।

इसे तत्वों को एक साथ रखने की अनुमति है, जो एकल इमोजी वर्ण, प्रस्तुति और संशोधक अनुक्रम हैं।

सामान्य रूप से इस तरह के अनुक्रम के लिए नियमित अभिव्यक्ति इस तरह दिखती है:

emoji_zwj_sequence := emoji_zwj_element (\x{200d} emoji_zwj_element )+

सभी के लिए नियमित अभिव्यक्ति

उपरोक्त सभी इमोजी अभ्यावेदन एक नियमित अभिव्यक्ति द्वारा वर्णित किए जा सकते हैं:

\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}] 
    ) 
  )*

-1

मैं एक ही समस्या थी और एक Stringऔर Characterएक्सटेंशन बनाने के लिए समाप्त हो गया ।

कोड पोस्ट करने के लिए बहुत लंबा है क्योंकि यह वास्तव में सभी इमोजीस (आधिकारिक यूनिकोड सूची v5.0 से) को सूचीबद्ध करता है, CharacterSetआप इसे यहां पा सकते हैं:

https://github.com/piterwilson/StringEmoji

स्थिरांक

चलो इमोजीच्रेकरसेट: कैरेक्टरसेट

सभी ज्ञात इमोजी युक्त वर्ण सेट (जैसा कि आधिकारिक यूनिकोड सूची 5.0 में वर्णित है http://unicode.org/emoji/charts-5.0/emoji-list.html )

तार

var ismoji: बूल {get}

Stringउदाहरण एक ज्ञात एकल इमोजी चरित्र का प्रतिनिधित्व करता है या नहीं

print("".isEmoji) // false
print("😁".isEmoji) // true
print("😁😜".isEmoji) // false (String is not a single Emoji)
var में ईमोजी: बूल {get}

Stringउदाहरण में एक ज्ञात इमोजी चरित्र है या नहीं

print("".containsEmoji) // false
print("😁".containsEmoji) // true
print("😁😜".containsEmoji) // true
var यूनिकोडनाम: स्ट्रिंग {get}

एक पर लागू होता है kCFStringTransformToUnicodeName- CFStringTransformस्ट्रिंग की एक प्रति पर

print("á".unicodeName) // \N{LATIN SMALL LETTER A WITH ACUTE}
print("😜".unicodeName) // "\N{FACE WITH STUCK-OUT TONGUE AND WINKING EYE}"
var niceUnicodeName: स्ट्रिंग {get}

हटाए गए उपसर्गों और प्रत्ययों के साथ kCFStringTransformToUnicodeName- का परिणाम देता हैCFStringTransform\N{}

print("á".unicodeName) // LATIN SMALL LETTER A WITH ACUTE
print("😜".unicodeName) // FACE WITH STUCK-OUT TONGUE AND WINKING EYE

चरित्र

var ismoji: बूल {get}

Characterउदाहरण एक ज्ञात इमोजी चरित्र का प्रतिनिधित्व करता है या नहीं

print("".isEmoji) // false
print("😁".isEmoji) // true
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.