新浪微博客户端(56)-拼接微博内容中的昵称,超链接,表情图片
DJStatusPart.h
#import <Foundation/Foundation.h> @interface DJStatusPart : NSObject /** 文本块内容 */ @property (nonatomic,copy) NSString *text; /** 文本块范围 */ @property (nonatomic,assign) NSRange range; /** 当前文本块是否是特殊文本(昵称,超链接,Emoji) */ @property (nonatomic,assign,getter=isSpecial) BOOL isSpecial; /** 当前文本块是否是表情图片 */ @property (nonatomic,assign,getter=isEmotion) BOOL isEmotion; @end
DJStatus.m
// 设置带属性的文本内容 - (void)setText:(NSString *)text { _text = text; // 将微博内容文本转换为带属性的微博内容文本 NSMutableAttributedString *attributedText = [self attributedTextWithText:text]; [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:14] range:NSMakeRange(0, attributedText.length)]; // 行间距 NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; [paragraphStyle setLineSpacing:2]; [attributedText addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedText.length)]; _attributedText = attributedText; } - (void)setRetweeted_status:(DJStatus *)retweeted_status { _retweeted_status = retweeted_status; DJUser *retwetedUser = retweeted_status.user; NSString *retweetedText = [NSString stringWithFormat:@"@%@: %@",retwetedUser.name,retweeted_status.text]; // 将转发内容文本转换为带属性的微博内容文本 NSMutableAttributedString *attributedText = [self attributedTextWithText:retweetedText]; [attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:13] range:NSMakeRange(0, attributedText.length)]; // 行间距 NSMutableParagraphStyle *paragraphSytle = [[NSMutableParagraphStyle alloc] init]; [paragraphSytle setLineSpacing:2]; [attributedText addAttribute:NSParagraphStyleAttributeName value:paragraphSytle range:NSMakeRange(0, attributedText.length)]; _retweetedAttributedText = attributedText; } /** 普通文本->属性文本 */ - (NSMutableAttributedString *)attributedTextWithText:(NSString *)text { // 表情的规则 NSString *emotionPattern = @"\\[[0-9a-zA-Z\\u4e00-\\u9fa5]+\\]"; // @的规则 NSString *atPattern = @"@[0-9a-zA-Z\\u4e00-\\u9fa5-_]+"; // #话题#的规则 NSString *topicPattern = @"#[0-9a-zA-Z\\u4e00-\\u9fa5]+#"; // url链接的规则 NSString *urlPattern = @"\\b(([\\w-]+://?|www[.])[^\\s()<>]+(?:\\([\\w\\d]+\\)|([^[:punct:]\\s]|/)))"; NSString *pattern = [NSString stringWithFormat:@"%@|%@|%@|%@", emotionPattern, atPattern, topicPattern, urlPattern]; // 利用当前文本生成attributedText NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init]; NSMutableArray *statusParts = [NSMutableArray array]; // 遍历并截取所有特殊文本 [text enumerateStringsMatchedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) { // 过滤掉长度为0的空字符串 if ((*capturedStrings).length == 0) return; DJStatusPart *statusPart = [[DJStatusPart alloc] init]; statusPart.text = *capturedStrings; statusPart.range = *capturedRanges; statusPart.isSpecial = YES; statusPart.isEmotion = [(*capturedStrings) hasPrefix:@"["] && [(*capturedStrings) hasSuffix:@"]"]; // 若当前文本块以[]打头和结尾,则认为是表情 [statusParts addObject:statusPart]; }]; // 遍历并截取所有非特殊文本 [text enumerateStringsSeparatedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) { // 过滤掉长度为0的空字符串 if ((*capturedStrings).length == 0) return; DJStatusPart *statusPart = [[DJStatusPart alloc] init]; statusPart.text = *capturedStrings; statusPart.range = *capturedRanges; statusPart.isSpecial = NO; statusPart.isEmotion = NO; [statusParts addObject:statusPart]; }]; // 对添加完毕的statusParts数组进行排序 [statusParts sortUsingComparator:^NSComparisonResult(DJStatusPart * _Nonnull obj1, DJStatusPart * _Nonnull obj2) { if (obj1.range.length > obj2.range.location) { return NSOrderedDescending; // 如果第一个文本块的位置坐标大于第二个,则为降序,否则为升序 } return NSOrderedAscending; }]; // 取出数组中的文本块进行拼接 for (DJStatusPart *part in statusParts) { NSAttributedString *subString = nil; if (part.isSpecial) { // 判断是否是特殊文本(若是特殊文本,则进行特殊处理,超链接:变色,表情文本:更换成表情图片) if (part.isEmotion) { // 判断当前文本块是否是表情 NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; attachment.image = [UIImage imageNamed:@"EmotionIcons/default/d_aini"]; attachment.bounds = CGRectMake(0, -4, 16, 16); subString = [NSAttributedString attributedStringWithAttachment:attachment]; } else { // 超链接&昵称 subString = [[NSAttributedString alloc] initWithString:part.text attributes:@{NSForegroundColorAttributeName : [UIColor blueColor]}]; } } else { // 不做任何处理 subString = [[NSAttributedString alloc] initWithString:part.text attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}]; } [attributedText appendAttributedString:subString]; } return attributedText; }
最终效果:
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库