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

如有不足之处欢迎指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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