iOS7 之前,幾乎所有的復(fù)雜文本都是通過 WebKit 來處理的龟再,無論 UILabel齿诞、UITextField 還是 UITextView 都在后臺以某種方式使用 webViews 來進(jìn)行文本布局和渲染咖杂。iOS7 以后宫静,蘋果提供了 TextKit 對文本進(jìn)行操作甥桂,并且對 UILabel柿究、UITextField、UITextView 都利用 TextKit 進(jìn)行了改造黄选。
前言
TextKit 簡介
TextKit是蘋果提供的一系列用于文字排版服務(wù)的類和協(xié)議的集合笛求,能夠幫助 app 存儲、布局和展示文本糕簿。TextKit 是以 CoreText 為基礎(chǔ)構(gòu)建的,所以能夠提供與 CoreText 相同的性能和能力狡孔。下圖展示了 TextKit 與 iOS 中其他文本和圖形框架的相互關(guān)系:
TextKit 在界面展示方面提供給了開發(fā)者在文本渲染之上的全部權(quán)限懂诗。
TextKit 中主要的類
TextKit 中主要包括三個類:NSTextStorage、NSLayoutManager 以及 NSTextContainer苗膝,這三個主要的類與 view 之間的關(guān)系如下圖:
-
NSTextStorage
是整個文本系統(tǒng)的數(shù)據(jù)來源殃恒,其管理著文本和文本屬性信息,它是NSMutableAttributedString
的一個子類辱揭。 -
NSTextContainer
定義了一個可以布局文本的區(qū)域离唐,并且也可以通過設(shè)置一個貝塞爾曲線數(shù)組的方式來為編輯區(qū)域設(shè)置排除區(qū)域,每個 Text View 都有一個 Text Container问窃,它精確地描述了這個可用的區(qū)域亥鬓。 -
NSLayoutManager
對文本系統(tǒng)的其他部分起到協(xié)調(diào)作用,將NSTextStorage
中存儲的文本信息渲染到視圖的展示區(qū)域域庇。NSLayoutManager
的工作主要包括以下幾個方面:監(jiān)聽 Text Storage 中文本或?qū)傩愿淖兊耐ㄖ陡辏坏┙邮盏酵ㄖ陀|發(fā)布局進(jìn)程;將NSTextStorage
中所有的字符翻譯為字形听皿;向它的 TextContainers 查詢文本可用以繪制的區(qū)域熟呛;這些區(qū)域被行逐步填充,而行又被字形逐步填充尉姨。一旦一行填充完畢庵朝,下一行開始填充;對于每一行又厉,布局管理器必須考慮斷行行為(放不下的單詞必須移到下一行)九府、連字符、內(nèi)聯(lián)的圖像附件等等覆致;當(dāng)布局完成昔逗,文本的當(dāng)前顯示狀態(tài)被設(shè)為無效,然后 Layout Manager 將前面幾步排版好的文本設(shè)給 Text View篷朵。
TextKit 中各主要部分之間的關(guān)系如下圖所示:
以編程的方式修改一個NSTextStorage
對象主要有三個階段:
- 向
NSTextStorage
對象發(fā)送beginEditing
消息來開啟接下來的一系列修改勾怒; - 通過
replaceCharactersInRange:withString:
和setAttributes:range:
方法來修改對象中存儲的字符或者字符屬性婆排,每次在調(diào)用這些方法的時候,textStorage 對象都會自動的調(diào)用edited:range:changeInLength:
方法笔链; - 修改結(jié)束后段只,發(fā)送
endEditing
消息,這樣會使 textStorage 對象向代理發(fā)送消息
textStorage:willProcessEditing:range:changeInLength:
并且調(diào)用對象本身的processEditing
方法鉴扫,之后向代理對象發(fā)送textStorage:didProcessEditing:range:changeInLength:
消息赞枕,最后, textStorage 對象會向其相關(guān)聯(lián)的 layout manager 對象發(fā)送
processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:
消息坪创,所有相關(guān)聯(lián)的 layout manager 會輪流通過這個消息重新計算字形位置炕婶。