经验之谈—正则表达式实现图文混排

来源:互联网 发布:千兆网络测速工具 编辑:程序博客网 时间:2024/05/21 16:21
  • 在项目中,我们经常需要发表情,以及经常需要将表情字符转换成表情。因为表情是一个图片,所以我们发给服务器的时候,实际上是发一段特殊的文字给服务器,然后转换成表情。以免浪费用户过多的流量。
  • 那接下来,我们就来介绍一下,如何使用正则表达式实现图文混排呢?
  • 为了以后的代码的管理方便,我们抽取出两个类:

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;}

看一下效果:
正则

正则表情

0 0
原创粉丝点击