Check if there is an emoji contained in a string

2019-02-08 18:54发布

I am getting the text size of a string with this

textSize = [[tempDict valueForKeyPath:@"caption.text"] sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(280, CGFLOAT_MAX) lineBreakMode: NSLineBreakByWordWrapping];

The only problem I have is that if the string only contains an emoji, my app crashes. Is there an easy way to check for emojis or do I have to create an array with all possible emojis and then check for them using that?

error:

-[NSNull sizeWithFont:constrainedToSize:lineBreakMode:]: unrecognized selector sent to instance 0x3aa88a60


if ([tempDict valueForKeyPath:@"caption.text"]){
            NSLog(@"%@", [tempDict valueForKeyPath:@"caption"]);
            //Measure the message label box height
            textSize = [[tempDict valueForKeyPath:@"caption.text"] sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(280, CGFLOAT_MAX) lineBreakMode: NSLineBreakByWordWrapping];
            int height = 320 + 20 + textSize.height;
            [cellHeight addObject:[NSNumber numberWithInt:height]];
}

11条回答
别忘想泡老子
2楼-- · 2019-02-08 19:20

it's too late reply into this but it's may help someone.

- (BOOL)stringContainsEmoji:(NSString *)string {

    __block BOOL returnValue = NO;

    [string enumerateSubstringsInRange:NSMakeRange(0, string.length)
                               options:NSStringEnumerationByComposedCharacterSequences
                            usingBlock:^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop)
     {
         const unichar hs = [substring characterAtIndex:0];
         const unichar ls = substring.length > 1 ? [substring characterAtIndex:1] : 0;

#define IS_IN(val, min, max) (((val) >= (min)) && ((val) <= (max)))

         if(IS_IN(hs, 0xD800, 0xDBFF))
         {
             if(substring.length > 1)
             {
                 const int uc = ((hs - 0xD800) * 0x400) + (ls - 0xDC00) + 0x10000;

                 // Musical: [U+1D000, U+1D24F]
                 // Enclosed Alphanumeric Supplement: [U+1F100, U+1F1FF]
                 // Enclosed Ideographic Supplement: [U+1F200, U+1F2FF]
                 // Miscellaneous Symbols and Pictographs: [U+1F300, U+1F5FF]
                 // Supplemental Symbols and Pictographs: [U+1F900, U+1F9FF]
                 // Emoticons: [U+1F600, U+1F64F]
                 // Transport and Map Symbols: [U+1F680, U+1F6FF]
                 if(IS_IN(uc, 0x1D000, 0x1F9FF))
                     returnValue = YES;
             }
         }
         else if(substring.length > 1 && ls == 0x20E3)
         {
             // emojis for numbers: number + modifier ls = U+20E3
             returnValue = YES;
         }
         else
         {
             if(        // Latin-1 Supplement
                hs == 0x00A9 || hs == 0x00AE
                // General Punctuation
                ||  hs == 0x203C || hs == 0x2049
                // Letterlike Symbols
                ||  hs == 0x2122 || hs == 0x2139
                // Arrows
                ||  IS_IN(hs, 0x2194, 0x2199) || IS_IN(hs, 0x21A9, 0x21AA)
                // Miscellaneous Technical
                ||  IS_IN(hs, 0x231A, 0x231B) || IS_IN(hs, 0x23E9, 0x23F3) || IS_IN(hs, 0x23F8, 0x23FA) || hs == 0x2328 || hs == 0x23CF
                // Geometric Shapes
                ||  IS_IN(hs, 0x25AA, 0x25AB) || IS_IN(hs, 0x25FB, 0x25FE) || hs == 0x25B6 || hs == 0x25C0
                // Miscellaneous Symbols
                ||  IS_IN(hs, 0x2600, 0x2604) || IS_IN(hs, 0x2614, 0x2615) || IS_IN(hs, 0x2622, 0x2623) || IS_IN(hs, 0x262E, 0x262F)
                ||  IS_IN(hs, 0x2638, 0x263A) || IS_IN(hs, 0x2648, 0x2653) || IS_IN(hs, 0x2665, 0x2666) || IS_IN(hs, 0x2692, 0x2694)
                ||  IS_IN(hs, 0x2696, 0x2697) || IS_IN(hs, 0x269B, 0x269C) || IS_IN(hs, 0x26A0, 0x26A1) || IS_IN(hs, 0x26AA, 0x26AB)
                ||  IS_IN(hs, 0x26B0, 0x26B1) || IS_IN(hs, 0x26BD, 0x26BE) || IS_IN(hs, 0x26C4, 0x26C5) || IS_IN(hs, 0x26CE, 0x26CF)
                ||  IS_IN(hs, 0x26D3, 0x26D4) || IS_IN(hs, 0x26D3, 0x26D4) || IS_IN(hs, 0x26E9, 0x26EA) || IS_IN(hs, 0x26F0, 0x26F5)
                ||  IS_IN(hs, 0x26F7, 0x26FA)
                ||  hs == 0x260E || hs == 0x2611 || hs == 0x2618 || hs == 0x261D || hs == 0x2620 || hs == 0x2626 || hs == 0x262A
                ||  hs == 0x2660 || hs == 0x2663 || hs == 0x2668 || hs == 0x267B || hs == 0x267F || hs == 0x2699 || hs == 0x26C8
                ||  hs == 0x26D1 || hs == 0x26FD
                // Dingbats
                ||  IS_IN(hs, 0x2708, 0x270D) || IS_IN(hs, 0x2733, 0x2734) || IS_IN(hs, 0x2753, 0x2755)
                ||  IS_IN(hs, 0x2763, 0x2764) || IS_IN(hs, 0x2795, 0x2797)
                ||  hs == 0x2702 || hs == 0x2705 || hs == 0x270F || hs == 0x2712 || hs == 0x2714 || hs == 0x2716 || hs == 0x271D
                ||  hs == 0x2721 || hs == 0x2728 || hs == 0x2744 || hs == 0x2747 || hs == 0x274C || hs == 0x274E || hs == 0x2757
                ||  hs == 0x27A1 || hs == 0x27B0 || hs == 0x27BF
                // CJK Symbols and Punctuation
                ||  hs == 0x3030 || hs == 0x303D
                // Enclosed CJK Letters and Months
                ||  hs == 0x3297 || hs == 0x3299
                // Supplemental Arrows-B
                ||  IS_IN(hs, 0x2934, 0x2935)
                // Miscellaneous Symbols and Arrows
                ||  IS_IN(hs, 0x2B05, 0x2B07) || IS_IN(hs, 0x2B1B, 0x2B1C) || hs == 0x2B50 || hs == 0x2B55
                )
             {
                 returnValue = YES;
             }
         }

#undef IS_IN
     }];

    return returnValue;
}
查看更多
等我变得足够好
3楼-- · 2019-02-08 19:21

@Simha.IC answer is great.

However it does not work with the new iOS 9.1 emojis'.

Simha.IC snippet is not detecting these ones:

查看更多
劫难
4楼-- · 2019-02-08 19:24

Simple Swift solution with checking every scalar in unicodeScalars are in the set CharacterSet.symbols

extension String {
    var containsEmoji: Bool {
        for scalar in unicodeScalars {
            if CharacterSet.symbols.contains(scalar) {
                return true
            }
        }

        return false
    }
}

But I found some emoji 1.0 items like ℹ️ is not classify as an emoji. So I create this checker:

extension Unicode.Scalar {
    extension Unicode.Scalar {
        var isEmojiMiscSymbol: Bool {
            switch self.value {
            case 0x2030...0x329F:   // Misc symbols
                return true
            default:
                return false
            }
        }
    }
}

And this is the checker which can detect ℹ️:

extension String {
    var containsEmoji: Bool {
        for scalar in unicodeScalars {
            if CharacterSet.symbols.contains(scalar) {
                return true
            } else if scalar.isEmojiMiscSymbol {
                return true
            }
        }

        return false
    }
}
查看更多
成全新的幸福
5楼-- · 2019-02-08 19:26

You can use this new framework

https://github.com/woxtu/NSString-RemoveEmoji

Usage:

if (string.isIncludingEmoji) 
{
   NSLog(@"String Contains Emoji");
}

else
{
  NSLog(@"String Doesn't Contains Emoji");
}
查看更多
趁早两清
6楼-- · 2019-02-08 19:34

This issue may occur if there are any characters past 0x00ff. In other words, there are many Unicode characters in addition to Emoji that you may need to account for. In order to see if there are any Unicode characters (beyond the boundary of extended ASCII) use the following.

extension String {

  var containsUnicodeCharacters: Bool {
    for scalar in unicodeScalars {
      if scalar.value > 0x00FF {
        return true
      }
    }
    return false
  }

}
查看更多
登录 后发表回答