参考:
http://www.cocoachina.com/industry/20131028/7250.html
http://blog.youkuaiyun.com/iunion/article/details/12185057
http://www.jianshu.com/p/2f72a5fa99f1
“Text Kit指的是UIKit框架中用于提供高质量排版服务的一些类和协议,它让程序能够存储,排版和显示文本信息,并支持排版所需要的所有特性,包括字距调整、连写、换行和对齐等。”
以前,如果我们想实现复杂的文本排版,例如在textView中显示不同样式的文本,或者图片和文字混排,你可能就需要借助于UIWebView或者深入研究一下Core Text。在iOS6中,UILabel、UITextField、UITextView增加了一个NSAttributedString属性,可以稍微解决一些排版问题,但是支持的力度还不够。现在Text Kit完全改变了这种现状。
Text Kit是基于Core Text构建的快速、先进的文本排版和渲染引擎,并且与UIKit很好的集合。UITextView,UITextField、UILabel都已经基于Text Kit重新构建,所以它们都支持分页文本、文本包装、富文本编辑、交互式文本着色、文本折叠和自定义截取等特性。所有这些UI控件现在都以同样的方式构建,在它们后面,一个NSTextStorage对象保存着文本的主要信息,它本身是NSMutableAttributedString的子类,支持分批编辑。这就意味着你可以改变一个范围内的字符的样式而不用整体替换文本内容。
NSAttributedString:字符串的属性,普通的字符串属性. NSMutableAttributedString:字符串的属性,可变动的字符串属性.
Text Kit架构
下面,我们通过图1(此图来自WWDC2013 Session 210)来了解一下Text Kit的架构。图1是基于iOS 7绘制的,从图中,我们可以看到Text Kit是基于Core Text构建的,它通过Core Text与Core Graphics进行交互。而UI控件(UILabel、UITextField和UITextView)则构建于Text Kit之上,可见这些文本控件可以利用Text Kit提供的API来对文字进行排版和渲染处理。 从图中我们也可以看到SDK提供的UIWebView是基于WebKit的,它不能使用Text Kit提供的功能。
下图显示了Text Kit中文本的保存、渲染和现实之间的关系。
1.NSTextStorage本身继承与NSMutableAttributedString,它是以attributed string的形式保存需要渲染的文本,并在文本内容改变的时候通知到对应的layout manager对象。通常你需要创建NSTextStorage的子类来在文本改变时进行文本显示样式的更新。
2.NSLayoutManager作为文本控件中的排版引擎接收保存的文本并在屏幕上渲染出来。
3.NSTextContainer描述了文本在屏幕上显示时的几何区域,每个text container与一个具体的UITextView相关联。如果你需要定义一个很复杂形状的区域来显示文本,你可能需要创建NSTextContainer子类。
要实现我们上面描述的动态文本格式化功能,我们需要创建NSTextStorage子类以便在用户输入文本的时候动态的增加文本属性。自定义了text storage后,我们需要替换调UITextView默认的text storage。
需要注意的是,你不能直接修改已有的AttributedString, 你需要把它copy出来,修改后再进行设置:
NSMutableAttributedString *labelText = [myLabel.attributedText mutableCopy];
[labelText setAttributes:...];
myLabel.attributedText = labelText;
Dynamic type:动态字体
iOS7增加了一项用户偏好设置:动态字体,用户可以通过显示与亮度-文字大小设置面板来修改设备上所有字体的尺寸。为了支持这个特性,意味着不要用systemFontWithSize:,而要用新的字体选择器preferredFontForTextStyle:。iOS提供了六种样式:标题,正文,副标题,脚注,标题1,标题2。例如:
Exclusion paths:排除路径
iOS 上的 NSTextContainer 提供了exclusionPaths,它允许开发者设置一个 NSBezierPath 数组来指定不可填充文本的区域。
NSTextStorage:它是NSMutableAttributedString的子类,里面存的是要管理的文本。
NSLayoutManager:管理文本布局方式
NSTextContainer:表示文本要填充的区域
如上图所示,它们的关系是 1 对 N 的关系。就是那样:一个 Text Storage 可以拥有多个 Layout Manager,一个 Layout Manager 也可以拥有多个 Text Container。这些多重性带来了多容器布局的特性:
1)将多个 Layout Manager 附加到同一个 Text Storage 上,可以产生相同文本的多种视觉表现,如果相应的 Text View 可编辑,那么在某个 Text View 上做的所有修改都会马上反映到所有 Text View 上。
2)将多个 Text Container 附加到同一个 Layout Manager 上,这样可以将一个文本分布到多个视图展现出来。