iOS 自定义图片表情

项目中的聊天功能需要发送和接收图片表情,查阅资料后决定使用富文本实现。思路如下:

  • 客户端之间约定一个标识符并定义一个正则表达式;

  • 将图片资源的名称与之保持一致,同时将资源文件导入到工程里,并新建一个plist文件便于取值;
    图片资源plist文件.png
  • 收到文本消息时(本质上是一个文本消息),使用之前约定的正则表达式对消息内容进行匹配并筛选出满足条件的字符串;

  • 使用富文本将字符串替换为图片并插入;

  • 发送图片表情消息时,将图片表情进行转义,转换成字符串。

话不多说,上代码

@interface RPConvertToCommonEmoticonsHelper : NSObject

//使用单例进行初始化
+ (instancetype)shareInstancetype;

/*!
 @method
 @brief 表情编码转换为图片png表情
 @param text   待转换的文字
 @return  转换后的富文本
 */
- (NSAttributedString *)convertToPNGEmoticons:(NSString *)text;

/*!
 @method
 @brief 判断消息是否包含图片表情
 @param text   待转换的文字
 @return  是否包含
 */
- (BOOL)isPNGEmotion:(NSString *)text;

/*!
 @method
 @brief 图片png表情转换成字符串(发送消息的时候需要转换)
 @param attributedString  待转换的富文本
 @return  转换后的字符串
 */
- (NSMutableString *)convertAttributedText:(NSAttributedString *)attributedString;

@end

//自定义的文本附件
@interface RPAttachment : NSTextAttachment

@property (nonatomic , copy) NSString * text;

@end
#import "RPConvertToCommonEmoticonsHelper.h"

static RPConvertToCommonEmoticonsHelper * convertToCommonEmoticonsHelper = nil;

@implementation RPConvertToCommonEmoticonsHelper

+ (instancetype)shareInstancetype{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        convertToCommonEmoticonsHelper = [[self alloc] init];
    });
    return convertToCommonEmoticonsHelper;
}

- (NSAttributedString *)convertToPNGEmoticons:(NSString *)text{
    if ([self isPNGEmotion:text]) {
        RPLog(@"消息包含图片表情 == %@ ",text);
        //表情标识的正则
        NSString *regex = @"你的正则";
        NSError *error;
        NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:&error];
        NSMutableAttributedString *string = [[ NSMutableAttributedString alloc ] initWithString:text attributes:nil ];
        if (!error) {
            // 对str字符串进行匹配
            NSArray *matches = [regular matchesInString:text options:0 range:NSMakeRange(0, text.length)];
            // 遍历匹配后的每一条记录
            for (NSTextCheckingResult *match in [matches reverseObjectEnumerator]) {
                NSRange range = [match range];
                NSString *mStr = [text substringWithRange:range];
                RPLog(@"%@", mStr);
                //自定义的文本附件 继承NSTextAttachment 并添加一个String类型的属性 将来转义的时候要用到
                RPAttachment *rpAttchImage = [[RPAttachment alloc] init];
                rpAttchImage.text = mStr;
                // 表情图片
                rpAttchImage.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png",mStr]];
                rpAttchImage.bounds = CGRectMake(x, y, width,height);
                NSAttributedString *tempString = [NSAttributedString attributedStringWithAttachment:rpAttchImage];
                if (rpAttchImage != nil) {
                    //插入表情
                    [string deleteCharactersInRange:range];
                    [string insertAttributedString:tempString atIndex:range.location];
                }
            }
        }
        //设置字体
        [string addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:NSMakeRange(0, string.length)];
        return string;
    }else{
        NSMutableAttributedString *string = [[ NSMutableAttributedString alloc ] initWithString:text attributes:nil ];
        //设置字体
        [string addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:NSMakeRange(0, string.length)];
        return string;
    }
}

- (BOOL)isPNGEmotion:(NSString *)text{
    //根据表情标识 匹配表情
    NSRegularExpression *numberRegular = [NSRegularExpression regularExpressionWithPattern:@"你的正则" options:NSRegularExpressionCaseInsensitive error:nil];
    NSInteger count = [numberRegular numberOfMatchesInString:text options:NSMatchingReportProgress range:NSMakeRange(0, text.length)];
    if (count > 0) {
        return YES;
    }else{
        return NO;
    }
}

- (NSMutableString *)convertAttributedText:(NSAttributedString *)attributedString{
    //转义回来
    NSMutableString *attStr = [[NSMutableString alloc] initWithString:attributedString.string];
    [attributedString enumerateAttribute:NSAttachmentAttributeName
                                 inRange:NSMakeRange(0, attributedString.length)
                                 options:NSAttributedStringEnumerationReverse
                              usingBlock:^(id value, NSRange range, BOOL *stop){
                                    if (value) {
                                        //拿到文本附件
                                        RPAttachment *attachment = (RPAttachment*)value;
                                        NSString *str = [NSString stringWithFormat:@"%@",attachment.text];
                                        //替换成图片表情的标识
                                        [attStr replaceCharactersInRange:range withString:str];
                                    }
    }];
    return attStr;
}

@end

@implementation RPAttachment

@end

效果如下


效果图.png

如有不足之处欢迎指正。

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,673评论 18 139
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,396评论 8 265
  • 1.感恩父母生养之恩,有你们才有我。谢谢! 2.感恩亲人,死党,朋友,老师的支持,你们给予我负重前行中的善意,谢谢...
    心灵陪伴阅读 186评论 0 6
  • 修修补补 反反复复的枷锁,如果是的话,一并给按它凌乱的格式扯碎 红胖子说的话越来越对了,可难道还指望如此便能获得谅...
    何解然阅读 104评论 0 0