iOS不倒,博客不停
好久没有更新简书了,因为新公司,真的很忙!前几天一直忙emoji,正好阳光明媚就记录一下
emoji在社交类APP很常用,比如发动态,圈子,还有回复评论,还有会话
在玩弄emoji 我想这位大神更牛逼:http://www.jianshu.com/p/3bfeb201794a
他介绍了emoji的历史还有emoji的原理,最后是一份非常漂亮的emoji键盘Demo
我这里记录的是一个我在开发过程比较恶心的东西:
后台在处理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解码与编码,其实原理也很简单:
这里我写了一个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; }