IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    emoji表情处理

    shendao发表于 2017-06-02 12:39:03
    love 0

    iOS不倒,博客不停

    好久没有更新简书了,因为新公司,真的很忙!前几天一直忙emoji,正好阳光明媚就记录一下

    emoji在社交类APP很常用,比如发动态,圈子,还有回复评论,还有会话

    emoji表情处理
    4EFD08C4-32F7-46F1-97A5-291B19D3EF03.png

    在玩弄emoji 我想这位大神更牛逼:http://www.jianshu.com/p/3bfeb201794a
    他介绍了emoji的历史还有emoji的原理,最后是一份非常漂亮的emoji键盘Demo

    我这里记录的是一个我在开发过程比较恶心的东西:

    Unicode与utf-8的转码;

    后台在处理emoji的态度,直接就是不处理,所以我们需要对emoji包括中文,数字,还有特殊字符进行编码还有解码

    //编码

    NSString *uniStr = [NSString stringWithUTF8String:[_barrageText.text UTF8String]]; NSData *uniData = [uniStr dataUsingEncoding:NSNonLossyASCIIStringEncoding]; NSString *goodStr = [[NSString alloc] initWithData:uniData encoding:NSUTF8StringEncoding] ; NSLog(@"---编码--->[%@]",goodStr);

    //解码

    const char *jsonString = [goodStr UTF8String];   // goodStr 服务器返回的 json NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)]; NSString *goodMsg1 = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding]; NSLog(@"---解码--->[%@]",goodMsg1);  2017-05-15 10:16:17.858 DFRomwe[650:153981] ---编码--->[hello/ud83d/ude18/ud83d/ude18world/u4e16/u754chaha/ud83d/ude17] 2017-05-15 10:16:17.859 DFRomwe[650:153981] ---解码--->[hello😘😘world世界haha😗]

    总想着事情就能这么轻松解决!!!
    可是,然后,呵呵呵,你不去了解一下东西,还是不行的
    果然,后台不作处理的情况下,如果返回JSON这就不行了,因为会默认带有转义字符: “/” 会导致下面这个情况:

     //在这里以😀表情为例,😀的Unicode编码为U+1F604,UTF-16编码为:/ud83d/ude04 NSString * emojiUnicode = @"/U0001F604"; NSLog(@"emojiUnicode:%@",emojiUnicode); //如果直接输入/ud83d/ude04会报错,加了转义后不会报错,但是会输出字符串/ud83d/ude04,而不是😀 NSString * emojiUTF16 = @"//ud83d//ude04"; NSLog(@"emojiUTF16:%@",emojiUTF16); //转换 emojiUTF16 = [NSString stringWithCString:[emojiUTF16 cStringUsingEncoding:NSUTF8StringEncoding] encoding:NSNonLossyASCIIStringEncoding]; NSLog(@"emojiUnicode2:%@",emojiUTF16);

    输出:

    emojiUnicode:😄 emojiUnicode1:/ud83d/ude04 emojiUnicode2:😄

    果断百度另外的方法

    //解码

    - (NSString *)decodeEmoji{     NSString *tepStr1 ;     if ([self containsString:@"////u"]) {         tepStr1 = [self stringByReplacingOccurrencesOfString:@"////u"withString:@"//U"];     }else{         tepStr1 = [self stringByReplacingOccurrencesOfString:@"//u"withString:@"//U"];     }     NSString *tepStr2 = [tepStr1 stringByReplacingOccurrencesOfString:@"/""withString:@"///""];     NSString *tepStr3 = [[@"/"" stringByAppendingString:tepStr2]stringByAppendingString:@"/""];     NSData *tepData = [tepStr3  dataUsingEncoding:NSUTF8StringEncoding];     NSString *axiba = [NSPropertyListSerialization  propertyListWithData:tepData options:NSPropertyListMutableContainers  format:NULL error:NULL];     return  [axiba stringByReplacingOccurrencesOfString:@"//r//n"withString:@"/n"]; }

    //编码

    - (NSString *)encodeEmoji{      NSUInteger length = [self length];     NSMutableString *s = [NSMutableString stringWithCapacity:0];      for (int i = 0;i < length; i++){         unichar _char = [self characterAtIndex:i];         //判断是否为英文和数字         if (_char <= '9' && _char >='0'){             [s appendFormat:@"%@",[self substringWithRange:NSMakeRange(i,1)]];         }else if(_char >='a' && _char <= 'z'){             [s appendFormat:@"%@",[self substringWithRange:NSMakeRange(i,1)]];         }else if(_char >='A' && _char <= 'Z')         {             [s appendFormat:@"%@",[self substringWithRange:NSMakeRange(i,1)]];         }else{             [s appendFormat:@"//"];              [s appendFormat:@"//u%x",[self characterAtIndex:i]];         }     }     return s;  }

    这是从JSON解码与编码,其实原理也很简单:

    • A :就是把多余的转义斜杠扔掉,
    • B :然后Unicode转utf-8;
    • C :然后utf-8转Unicode;

    这里我写了一个NSString的一个分类:#import “NSString+Emoji.h”

    还添加了一些方法:

    //判断是否存在emoji表情:因为emoji表情室友Unicode编码区间的

    + (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];                                 if (0xd800 <= hs && hs <= 0xdbff) {                                     if (substring.length > 1) {                                         const unichar ls = [substring characterAtIndex:1];                                         const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;                                         if (0x1d000 <= uc && uc <= 0x1f77f) {                                             returnValue = YES;                                         }                                     }                                 } else if (substring.length > 1) {                                     const unichar ls = [substring characterAtIndex:1];                                     if (ls == 0x20e3) {                                         returnValue = YES;                                     }                                 } else {                                     if (0x2100 <= hs && hs <= 0x27ff) {                                         returnValue = YES;                                     } else if (0x2B05 <= hs && hs <= 0x2b07) {                                          returnValue = YES;                                     } else if (0x2934 <= hs && hs <= 0x2935) {                                         returnValue = YES;                                     } else if (0x3297 <= hs && hs <= 0x3299) {                                         returnValue = YES;                                     } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {                                         returnValue = YES;                                     }                                 }                              }];     return returnValue; }

    //判断是否存在中文
    //因为要保证之前的utf-8的数据也能显示

    - (BOOL)includeChinese {     for(int i=0; i< [self length];i++)     {         int a =[self characterAtIndex:i];         if( a >0x4e00&& a <0x9fff){             return YES;         }     }     return NO; }

    //判断是否以中文开头

     - (BOOL)JudgeChineseFirst{      //是否以中文开头(unicode中文编码范围是0x4e00~0x9fa5)     int utfCode = 0;     void *buffer = &utfCode;     NSRange range = NSMakeRange(0, 1);     //判断是不是中文开头的,buffer->获取字符的字节数据 maxLength->buffer的最大长度 usedLength->实际写入的长度,不需要的话可以传递NULL encoding->字符编码常数,不同编码方式转换后的字节长是不一样的,这里我用了UTF16 Little-Endian,maxLength为2字节,如果使用Unicode,则需要4字节 options->编码转换的选项,有两个值,分别是NSStringEncodingConversionAllowLossy和NSStringEncodingConversionExternalRepresentation range->获取的字符串中的字符范围,这里设置的第一个字符 remainingRange->建议获取的范围,可以传递NULL     BOOL b = [self getBytes:buffer maxLength:2 usedLength:NULL encoding:NSUTF16LittleEndianStringEncoding options:NSStringEncodingConversionExternalRepresentation range:range remainingRange:NULL];     if (b && (utfCode >= 0x4e00 && utfCode <= 0x9fa5))         return YES;     else         return NO; }


沪ICP备19023445号-2号
友情链接