富文本 NSAttributedString 在开发中经常用得到,虽然很实用,但是代码写起来却并不那么漂亮:
|
|
看着不怎么美观。所以长久以来总是想要封装一下 NSAttributedString,但是又没什么好的思路。
这两天突然想起了链式编程这个词,琢磨着要不玩一下呗。
|
|
|
|
挺好玩诶
可是要怎么应用到 NSAttributedString 上呢?
我们的目标是消除 NSAttributedStringKey,专注于 value 上,让代码能像这样写:
|
|
封装思路
WZAttributesBuilder
为了消除 NSAttributedStringKey,专注于 value,我们需要将 NSAttributedStringKey 封装起来。为此我们需要创建一个类来装载这些 value:WZAttributesBuilder。
|
|
这里需要提的是 NSWritingDirectionAttributeName(书写方向)的值,因为这个值需要是@[@(NSWritingDirection | NSWritingDirectionFormatType)] 的形式,所以我自定义了一个枚举来封装这些可能的值:
测试之后发现只有 “Right to Left, Override” 的模式才能让书写方向由右往左书写,“Right to Left, Embed” 并不能达到这种效果。
苹果文档 对 NSWritingDirectionEmbedding 的解释:
Text is embedded in text with another writing direction. For example, an English quotation in the middle of an Arabic sentence could be marked as being embedded left-to-right text.
大概意思:一些文字以其他书写方向嵌入到一段文字中。比如一段阿拉伯文字中间嵌入一段英文文字,这段英文文字可以以从左向右的方向嵌入。
一开始没理解,查了一下阿拉伯文字的书写方向,发现是从右向左书写的。(= = )
虽然这么说,但是我并不知道该怎么测试 ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄
WZAttributeRange
有了封装 NSAttributedStringKey 的类了,就要开始构思如何做到attrStr.range(0, 2).attributes(...)。我们可以认为attrStr.attributes(...)是attrStr.range(0, attrStr.length).attributes(...)的简写形式。所以我们将围绕attrStr.range(0, 2).attributes(...)的形式来实现。
这里的问题只在于 range(0, 2) 应该返回什么值。1. 返回 NSAttributedString 对象,那么 NSAttributedString 对象需要保存一个 NSRange 变量;2. 返回一个第三方对象,那么这个对象需要保存一个 NSRange 变量,并实现 .attributes(...);
我这里用了第二种方法,至于为什么,因为我是稀里糊涂就做了的 ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄。
因此我们创建 WZAttributeRange 类,具体实现:
|
|
这个类就这样,好像也没什么好说的了。需要注意的是,attributes()是用addAttributes 而不是 setAttributes。
可能存在的问题大概是调用链比较长的时候,会频繁创建 WZAttributeRange 和 WZAttributesBuilder 对象。
NSAttributedString(WZAttributeChain)
材料都准备好了,就可以开始对 NSAttributedString 动刀了。我们需要两个最基本的东西:range(loc, len) 和 attributes(...),考虑到经常需要拼接其他 attributedString,所以加多一个append(attributedString)。
|
|
这里也好像没什么好说的,就是通过 runtime 给 NSAttributedString 添加三个 block 属性,并且实现它们。
不过这里没有做线程安全,感觉没什么必要。
这里存在的问题是 attrStr1.attributes(...) return attrStr2 attrStr1 和 attrStr2 已经不是同一个对象了,这点要注意!
如果需要返回对象是原来的对象,就需要用到 NSMutableAttributedString 了。因为工作机制不一样,所以我们需要通过 NSMutableAttributedString 的分类 WZAttributeChain 重新实现这三个 block。不过代码都差不多,就不贴出来了。
集成 WZAttributedStringChain
pod ‘WZAttributedStringChain’
WZAttributedStringChain 使用方法
假设我们要在 label 上显示下图这段富文本,这也是最上面那段原生 NSAttributedString 的输出结果:

给定了三个字符串:
|
|