效果.jpeg日常开发中绝大部分需求只需要生成和显示富文本即可,但是有没有一种办法将富文本变成部分可替换,可再加工的办法呢?苦苦思索,灵光一闪,记录下来;大体思路是封装 enumerateAttributes 方法的二次封装,获取整个富文本组成的所有子NSAttributedString,然后用 NSStringFromRange 作为键封装成字典
rangeSubAttStringDic,字典的键 NSRange 字符串经过排序就是各个片段对应的键,进而获取对应的 子NSAttributedString,再通过下标方法可以非常简单的根据索引替换富文本中任意部分的内容。
- (void)effectiveRange {
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"BoBiBu"];
[attString addAttribute:NSBackgroundColorAttributeName
value:[UIColor systemGreenColor]
range:NSMakeRange(0, 2)];
[attString addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:12]
range:NSMakeRange(0, 2)];
[attString addAttribute:NSFontAttributeName
value:[UIFont italicSystemFontOfSize:12]
range:NSMakeRange(2, 2)];
[attString addAttribute:NSBackgroundColorAttributeName
value:[UIColor systemRedColor]
range:NSMakeRange(2, 2)];
NSLog(@"AttributedString: %@", attString);
NSDictionary<NSString *, NSAttributedString *> *dic = attString.rangeSubAttStringDic;
NSArray *allKeys = [dic.allKeys sortedArrayUsingSelector:@selector(compare:)];
DDLog(@"compare_%@", allKeys);
DDLog(@"dic: %@", dic);
[dic enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSAttributedString * _Nonnull obj, BOOL * _Nonnull stop) {
NSAttributedString *subAttString = [attString attributedSubstringFromRange:NSRangeFromString(key)];
NSLog(@"attributedSubstring: %@", subAttString);
}];
}
//日志
2020-12-08 11:00:57.105140+0800 SwiftTemplet[71849:17013190] AttributedString: Bo{
NSBackgroundColor = "<UIDynamicSystemColor: 0x600003fbc9a0; name = systemGreenColor>";
NSFont = "<UICTFont: 0x7fc5d2431a60> font-family: \".SFUI-Semibold\"; font-weight: bold; font-style: normal; font-size: 12.00pt";
}Bi{
NSBackgroundColor = "<UIDynamicSystemColor: 0x600003e13620; name = systemRedColor>";
NSFont = "<UICTFont: 0x7fc5d2432750> font-family: \".SFUI-RegularItalic\"; font-weight: normal; font-style: italic; font-size: 12.00pt";
}Bu{
}
2020-12-08 11:00:57.105774+0800 SwiftTemplet[71849:17013190] -[AttrStringEffectiveController effectiveRange] [Line 98] compare_(
"{0, 2}",
"{2, 2}",
"{4, 2}"
)
2020-12-08 11:00:57.106189+0800 SwiftTemplet[71849:17013190] -[AttrStringEffectiveController effectiveRange] [Line 99] dic: {
"{0, 2}" = "Bo{\n NSBackgroundColor = \"<UIDynamicSystemColor: 0x600003fbc9a0; name = systemGreenColor>\";\n NSFont = \"<UICTFont: 0x7fc5d2431a60> font-family: \\\".SFUI-Semibold\\\"; font-weight: bold; font-style: normal; font-size: 12.00pt\";\n}";
"{2, 2}" = "Bi{\n NSBackgroundColor = \"<UIDynamicSystemColor: 0x600003e13620; name = systemRedColor>\";\n NSFont = \"<UICTFont: 0x7fc5d2432750> font-family: \\\".SFUI-RegularItalic\\\"; font-weight: normal; font-style: italic; font-size: 12.00pt\";\n}";
"{4, 2}" = "Bu{\n}";
}
2020-12-08 11:00:57.106877+0800 SwiftTemplet[71849:17013190] attributedSubstring: Bi{
NSBackgroundColor = "<UIDynamicSystemColor: 0x600003e13620; name = systemRedColor>";
NSFont = "<UICTFont: 0x7fc5d2432750> font-family: \".SFUI-RegularItalic\"; font-weight: normal; font-style: italic; font-size: 12.00pt";
}
2020-12-08 11:00:57.266799+0800 SwiftTemplet[71849:17013190] attributedSubstring: Bo{
NSBackgroundColor = "<UIDynamicSystemColor: 0x600003fbc9a0; name = systemGreenColor>";
NSFont = "<UICTFont: 0x7fc5d2431a60> font-family: \".SFUI-Semibold\"; font-weight: bold; font-style: normal; font-size: 12.00pt";
}
2020-12-08 11:00:57.267058+0800 SwiftTemplet[71849:17013190] attributedSubstring: Bu{
}
@objc public extension NSAttributedString{
///获取所有的 [Range: NSAttributedString] 集合
var rangeSubAttStringDic: [String : NSAttributedString]{
get{
var dic = [String : NSAttributedString]()
enumerateAttributes(in: NSMakeRange(0, self.length), options: .longestEffectiveRangeNotRequired) { (attrs, range, _) in
let sub = self.attributedSubstring(from: range)
dic[NSStringFromRange(range)] = sub
}
return dic;
}
}
public extension NSMutableAttributedString{
///获取或者替换某一段 NSAttributedString
subscript(index: NSInteger) -> NSAttributedString?{
get {
let keys = rangeSubAttStringDic.keys.sorted()
if index < 0 || index >= keys.count {
return nil
}
let key = keys[index]
return rangeSubAttStringDic[key]
}
set {
guard let newValue = newValue else { return }
let keys = rangeSubAttStringDic.keys.sorted()
if index < 0 || index >= keys.count {
return
}
let key = keys[index]
replaceCharacters(in: NSRangeFromString(key), with: newValue)
}
}
网友评论