emoji表情处理

iOS不倒,博客不停

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

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

4EFD08C4-32F7-46F1-97A5-291B19D3EF03.png

在玩弄emoji 我想这位大神更牛逼://www.greatytc.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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容