TextKit 探究

iOS 7 引入了一個(gè)非常有用的新功能TextKit窒百,使開發(fā)者可以通過方便的接口去修改文字的樣式和排版,而不需要直接操作復(fù)雜的Core Text。本文將從以下幾個(gè)方面闡述TextKit的使用:

  • 什么是TextKit
  • TextKit的架構(gòu)
  • TextKit的作用
  • TextKit中重要的類
  • TextKit的具體使用
  • 對TextKit的總結(jié)
  • 參考的學(xué)習(xí)資料

什么是TextKit

在iOS7中,蘋果引入了Text Kit——Text Kit是一個(gè)快速而又現(xiàn)代化的文字排版和渲染引擎。Text Kit在UIKit framework中的定義了一些類和相關(guān)協(xié)議复局,它最主要的作用就是為程序提供文字排版和渲染的功能。在程序中粟判,通過Text Kit可以對文字進(jìn)行存儲(store)亿昏、布局(lay out),以及用最精細(xì)的排版方式(例如文字間距档礁、換行和對齊等)來顯示文本內(nèi)容角钩。
蘋果引入Text Kit的目的并非要取代已有的Core Text,Core Text的主要作用也是用于文字的排版和渲染中,它是一種先進(jìn)而又處于底層技術(shù)彤断,如果我們需要將文本內(nèi)容直接渲染到圖形上下文(Graphics context)時(shí)野舶,從性能和易用性來考慮,最佳方案就是使用Core Text宰衙。而如果我們直接利用蘋果提供的一些控件(例如UITextView平道、UILabel和UITextField等)對文字進(jìn)行排版,無疑就是借助于UIkit framework中Text Kit提供的API供炼。

上面那段是引用破船博客里面的解釋的一屋。按照我個(gè)人的理解,TextKit的引入主要是為了解決Core Text復(fù)雜難用袋哼,如果只是從解決大部分功能來說冀墨,使用TextKit的開發(fā)效率會比Core Text高。TextKit 只是 對Core Text進(jìn)行了一些易用性封裝涛贯,解決一些諸如簡單文字排版诽嘉,文字樣式變換等基本需求。如果需要更強(qiáng)的運(yùn)行性能和更強(qiáng)大的靈活性弟翘,TextKit是不能滿足要求的虫腋,這時(shí)候需要Core Text。

TextKit的架構(gòu)

可以從圖中看出稀余,原生的文本控件都是構(gòu)建在TextKit之上的悦冀,使用TextKit進(jìn)行排版和渲染。而UIWebView是構(gòu)建在WebKit上的睛琳,不能使用TextKit功能盒蟆。

TextKit的作用

兩個(gè)最重要的功能:

  • 文字排版
  • 文字渲染

TextKit中重要的類

如圖所示,TextKit中有四個(gè)重要對象:

  • TextView:主要是指UILabel师骗,UITextField历等,UITextView這些文本控件
  • TextContainer:對應(yīng)TextKit中的NSTextContainer,主要作用是定義排版區(qū)域辟癌,區(qū)域可以是圓形矩形甚至是不規(guī)則的圖形募闲,也可以定義不能填充的區(qū)域來顯示非文本元素。
  • Layout Manager:對應(yīng)TextKit中的NSLayoutManager愿待,主要作用是定義布局方式,使文本內(nèi)容按照一定的布局方式進(jìn)行排版靴患。
  • Text Storage:對應(yīng)TextKit中的NSTextStorage仍侥,繼承自NSMutableAttributedString,主要作用是存儲文本字符和文本相關(guān)屬性鸳君。當(dāng)NSTextStorage的屬性發(fā)生變化時(shí)农渊,會通知NSLayoutManager進(jìn)行重新排版。

通常情況下或颊,一個(gè)NSTextStorage 對應(yīng) 一個(gè)NSLayoutManager 對應(yīng) 一個(gè) NSTextContainer砸紊。


當(dāng)文字顯示為多列传于、多頁時(shí),一個(gè)NSLayoutManager 對應(yīng) 多個(gè) NSTextContainer醉顽。


當(dāng)采用不同的排版方式時(shí)沼溜,一個(gè)NSTextStorage對應(yīng)多個(gè)NSLayoutManager。


四個(gè)重要對象的協(xié)同方式(引用自破船的博客游添,一句話解析的非常清楚):

通常由NSLayoutManager從NSTextStorage中讀取出文本數(shù)據(jù)系草,然后根據(jù)一定的排版方式,將文本排版到NSTextContainer中唆涝,再由NSTextContainer結(jié)合UITextView將最終效果顯示出來找都。

TextKit的具體使用

1.只使用NSAttributedString實(shí)現(xiàn)簡單的文字高亮

let attributedString = NSMutableAttributedString(attributedString: textView.attributedText!)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.RedColor(), range: itemRange)
textView.attributedText = attributedString

可以直接使用 NSAttributedString 來設(shè)置文本的樣式,但這個(gè)功能還是比較簡單廊酣,不能設(shè)置布局還有不能處理圖文混排的情況能耻。

2.使用Text Storage實(shí)現(xiàn)文字高亮

        // frame
        let frame = self.view.bounds

        // TextStorage , LayoutManager , TextContainer
        let textStorage = NSTextStorage()

        let layoutManager = NSLayoutManager()
        textStorage.addLayoutManager(layoutManager)

        let textContainer = NSTextContainer(size: frame.size)
        layoutManager.addTextContainer(textContainer)

        textView = UITextView(frame: frame, textContainer: textContainer)

        // textView
        self.view.addSubview(textView)
        textView.editable = false
        textView.selectable = false
        let txtString = String.txtString(filename: "lorem", filetype: "txt")  // 從文本文件中讀取數(shù)據(jù)

        textView.textStorage.replaceCharactersInRange(NSMakeRange(0, 0), withString: txtString)

調(diào)用函數(shù)_highlight() 實(shí)現(xiàn) 前 201 個(gè)字變紅色功能。

    /**
     語法高亮
     */
    private func _highlight() {
        textView.textStorage.beginEditing()

        // 屬性描述字典
        let attributesDict = [NSForegroundColorAttributeName:UIColor.redColor()]

        textView.textStorage.setAttributes(attributesDict, range: NSMakeRange(0, 200))

        textView.textStorage.endEditing()
    }

要對NSTextStorage的屬性進(jìn)行變更前亡驰,要加入

textView.textStorage.beginEditing()

通過這句來開啟textView中textStorage的編輯模式晓猛。
編輯屬性完成后要通過下面這句代碼來結(jié)束編輯模式,并通知NSLayoutManager來更新布局和渲染隐解。

textView.textStorage.endEditing()

3.文本元素與非文本元素混排

TimeIndicatorView 是一個(gè)非文本元素鞍帝,是一個(gè)自定義的UIView子類。

        // TimeIndicatorView
        timeIndicatorView = TimeIndicatorView(frame: CGRectMake(100,100,100,100))
        timeIndicatorView.text = "卡卡卡卡卡卡卡卡卡卡"
        textView.addSubview(timeIndicatorView)

TimeIndicatorView的形狀是圓形煞茫,所以要對textContainer中的exclusionPaths設(shè)置成相應(yīng)的圓形路徑帕涌,這圓形內(nèi)不進(jìn)行文字的排版和渲染,也就是說排除這個(gè)圓形的填充區(qū)域续徽。

    /**
     遮蓋范圍
     */
    private func _updateExclusionPaths() {
        var circleFrame = self.textView.convertRect(timeIndicatorView.bounds, fromView: timeIndicatorView) // 坐標(biāo)轉(zhuǎn)換
        circleFrame.origin.x = circleFrame.origin.x - textView.textContainerInset.left
        circleFrame.origin.y = circleFrame.origin.y - textView.textContainerInset.top
        let circlePath = UIBezierPath(roundedRect: circleFrame, cornerRadius: timeIndicatorView.radius())
        textView.textContainer.exclusionPaths = [circlePath]
    }

效果圖:


對TextKit的總結(jié)

上面的例子這是實(shí)現(xiàn)了一些很簡單的功能蚓曼,通過這些簡單功能來演示一下TextKit在文本排版和文本渲染的強(qiáng)大功能。這里是用Swift寫的TextKit演示的demo:TextKitDemo钦扭。這里沒有對NSTextContainer纫版,NSTextStorage,NSLayoutManager這三個(gè)進(jìn)行定制客情,事實(shí)上可以通過對這三個(gè)的定制來實(shí)現(xiàn)非常強(qiáng)大的排版和渲染功能其弊,由于本人對TextKit的理解還比較淺,所以這里就不進(jìn)行深究了膀斋。

參考的學(xué)習(xí)資料

Text Kit Tutorial: Getting Started
Using Text Kit to Manage Text in Your iOS Apps
TextKit學(xué)習(xí)(三)NSTextStorage梭伐,NSLayoutManager,NSTextContainer和UITextView
iOS 7中文字排版和渲染引擎——Text Kit
iOS 7 教程:淺析Text Kit
TextKit

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仰担,一起剝皮案震驚了整個(gè)濱河市糊识,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖赂苗,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愉耙,死亡現(xiàn)場離奇詭異,居然都是意外死亡拌滋,警方通過查閱死者的電腦和手機(jī)朴沿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸠真,“玉大人悯仙,你說我怎么就攤上這事》途恚” “怎么了锡垄?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祭隔。 經(jīng)常有香客問我货岭,道長,這世上最難降的妖魔是什么疾渴? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任千贯,我火速辦了婚禮,結(jié)果婚禮上搞坝,老公的妹妹穿的比我還像新娘搔谴。我一直安慰自己,他們只是感情好桩撮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布敦第。 她就那樣靜靜地躺著,像睡著了一般店量。 火紅的嫁衣襯著肌膚如雪芜果。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天融师,我揣著相機(jī)與錄音右钾,去河邊找鬼。 笑死旱爆,一個(gè)胖子當(dāng)著我的面吹牛舀射,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怀伦,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼后控,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了空镜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吴攒,沒想到半個(gè)月后张抄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洼怔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年署惯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镣隶。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡极谊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出安岂,到底是詐尸還是另有隱情轻猖,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布域那,位于F島的核電站咙边,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏次员。R本人自食惡果不足惜败许,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淑蔚。 院中可真熱鬧市殷,春花似錦、人聲如沸刹衫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绪妹。三九已至甥桂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邮旷,已是汗流浹背黄选。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留婶肩,地道東北人办陷。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像律歼,于是被迫代替她去往敵國和親民镜。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Text Kit學(xué)習(xí)(入門和進(jìn)階): http://www.cocoachina.com/industry/201...
    F麥子閱讀 3,998評論 1 13
  • 內(nèi)容來自于 iOS文檔中 About Text Handling in iOS 部分 ios平臺提供了顯示及編輯文...
    縱橫而樂閱讀 6,735評論 2 21
  • TextKit 的基本介紹 TextKit is a full-featured, high-level set ...
    Laughingg閱讀 1,121評論 0 1
  • 10點(diǎn)左右醒险毁,又花一小時(shí)選好了夾克制圈,然后洗漱吃午飯们童。 下午生化6,打完了克里斯篇鲸鹦。我好像知道這個(gè)游戲?yàn)槭裁幢粐娏耍?..
    AJI米閱讀 108評論 0 0
  • 喜歡烘焙大概好多年了慧库,懶癌終究戰(zhàn)勝了愛好,停下了好久沒碰過各類甜品了馋嗜。 有一天齐板,突發(fā)奇想非要開個(gè)做各類菜的公眾號,...
    心怡雨文閱讀 537評論 0 1