- 在项目中,我们经常需要发表情,以及经常需要将表情字符转换成表情。因为表情是一个图片,所以我们发给服务器的时候,实际上是发一段特殊的文字给服务器,然后转换成表情。以免浪费用户过多的流量。
- 那接下来,我们就来介绍一下,如何使用正则表达式实现图文混排呢?
- 为了以后的代码的管理方便,我们抽取出两个类:
NSString+Regular.h中,我们暴露两个方法出来:
/** * 返回正则表达式匹配的第一个结果 * * @param pattern 正则表达式 * * @return 匹配的第一个结果 是NSTextCheckingResult类型 */
- (NSTextCheckingResult *)firstMacthWithPattern:(NSString *)pattern;
- (NSArray <NSTextCheckingResult *> *)machesWithPattern:(NSString *)pattern;
NSString+Regular.m中,我们实现一下这两个方法:
- (NSTextCheckingResult *)firstMacthWithPattern:(NSString *)pattern
{
//正则表达式的创建很容易失败,注意捕获错误
NSError *error = nil;
//根据正则表达式创建实例
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
if ( error)
{
NSLog(@"正则表达式创建失败");
return nil;
}
//匹配出结果
NSTextCheckingResult *result = [regular firstMatchInString:self options:0 range:NSMakeRange(0,self.length)];
if ( result)
{
NSLog(@"匹配");
return result;
}else
{
NSLog(@"不匹配");
return nil;
}
}
- (NSArray <NSTextCheckingResult *> *)machesWithPattern:(NSString *)pattern
{
NSError *error = nil;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
if (error)
{
NSLog(@"正则表达式创建失败");
return nil;
}
return [expression matchesInString:self options:0 range:NSMakeRange(0,self.length)];
}
我们进而对NSTextAttachment写一个子类
ZYTextAttachment.h 中 我们暴露一个方法出来:
@interface ZYTextAttachment : NSTextAttachment
- (instancetype)initWithImage:(UIImage *)image;
@end
ZYTextAttachment.m中,我们实现一下:
#import "ZYTextAttachment.h"
@implementation ZYTextAttachment
- (instancetype)initWithImage:(UIImage *)image
{
if (self = [super init])
{
self.image = image;
}
return self;
}
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyPHPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex
{
return CGRectMake(0,-lineFrag.size.height * 0.2,lineFrag.size.height,lineFrag.size.height);
}
接下来,我们在viewController中,
- (void)viewDidLoad {
[super viewDidLoad];
self.label.text = @"二货[smiley_2],你在干嘛呢[smiley_6] 一起吃饭?[smiley_44]!";
}
然后在下面的方法中:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSString *content = self.label.text;
//匹配表情文字
NSString *pattern = @"\\[\\w+\\]";
NSArray *resultArr = [content machesWithPattern:pattern];
if (!resultArr) return;
NSMutableAttributedString *attrContent = [[NSMutableAttributedString alloc]initWithString:content];
NSUInteger lengthDetail = 0;
//遍历所有的result 取出range
for (NSTextCheckingResult *result in resultArr) {
//取出图片名
NSString *imageName = [content substringWithRange:NSMakeRange(result.range.location + 1,result.range.length - 2)];
// 创建AttributeString,来包装图片
ZYTextAttachment *attachment = [[ZYTextAttachment alloc]initWithImage:[UIImage imageNamed:imageName]];
// 将附近包装到NSAttributedString中
NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:attachment];
//图片附件的文本长度是1
NSLog(@"%zd",imageString.length);
NSUInteger length = attrContent.length;
NSRange newRange = NSMakeRange(result.range.location - lengthDetail,result.range.length);
[attrContent replaceCharactersInRange:newRange withAttributedString:imageString];
lengthDetail += length - attrContent.length;
}
//更新到label上
self.label.attributedText = attrContent;
}
看一下效果: