0

I am trying to detect if a user of my app entered an emoji into UITextView. I have found this code:

https://gist.github.com/cihancimen/4146056

However this code is not working for all emojis (for instance it is not working for the hearth symbol). Does anyone have a clue how to improve the code to catch all emojis? I am using Objective-C language. Any help is appreciated.

Jeavy
  • 13
  • 4

2 Answers2

1

This is how I do it in my app :

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if textView.textInputMode?.primaryLanguage == "emoji" || textView.textInputMode?.primaryLanguage == nil {
        // An emoji was typed by the user
        // Do anything you need to do (or return false to disallow emojis)
    }

    return true
}
Dean
  • 1,512
  • 13
  • 28
  • Thank you. I used to check it this way too while typing a text. But I changed the logic of application and now I need to detect it when user tries to send the text after pressing the button to send the text to server. So the checking should not occur on the fly while the user is typing but after pressing the button. Do you know how to change your code in order to accomplish this? Thank you. – Jeavy Oct 19 '16 at 09:55
1

If you need to be able to detect any emoji, you'll need to create a list containing all code points used for emoji (or a list of all emoji if you prefer). If you want to, you can look at how emoji are detected in this framework, which I created for the purpose of replacing standard emoji with custom images, or take a look at my answer to a related question.

Then, if you're working with Objective-C and the NSString type, you'll first have to convert the string's unichars (which are UTF-16 encoded) into UTF-32 compatible format in order to use your list of code points. When you have the UTF-32 value, just compare it against your list and handle it however you need:

// Sample text.
NSString *text = @"a ";

// Get the UTF-16 representation of the text.
unsigned long length = text.length;
unichar buffer[length];
[text getCharacters:buffer];

// Initialize array to hold our UTF-32 values.
NSMutableArray *array = [[NSMutableArray alloc] init];

// Temporary stores for the UTF-32 and UTF-16 values.
UTF32Char utf32 = 0;
UTF16Char h16 = 0, l16 = 0;

for (int i = 0; i < length; i++) {
    unichar surrogate = buffer[i];

    // High surrogate.
    if (0xd800 <= surrogate && surrogate <= 0xd83f) {
        h16 = surrogate;
        continue;
    }
    // Low surrogate.
    else if (0xdc00 <= surrogate && surrogate <= 0xdfff) {
        l16 = surrogate;

        // Convert surrogate pair to UTF-32 encoding.
        utf32 = ((h16 - 0xd800) << 10) + (l16 - 0xdc00) + 0x10000;
    }
    // Normal UTF-16.
    else {
        utf32 = surrogate;
    }

    // Compare the UTF-32 value against your list of code points, and handle.
    // Just demonstrating with the code point for .
    if (utf32 == 0x1f601) {
        NSLog(@"It's an emoji!");
    }

}

Additionally, you'll need to handle Variation Selectors if you don't want false positives, and zero-width joiners if you need to be able to handle sequences, but just looking at the first character in a sequence will tell you whether the string contains an emoji, so I won't go further into this.

Community
  • 1
  • 1
xoudini
  • 7,001
  • 5
  • 23
  • 37