猿題庫iOS客戶端的技術細節(三):基於CoreText的排版引擎
來自:http://blog.devtang.com/blog/2013/10/21/the-tech-detail-of-ape-client-3/
前言
本人今年主要在負責猿題庫iOS客戶端的開發,本文旨在通過分享猿題庫iOS客戶端開發過程中的技術細節,達到總結和交流的目的。
這是本技術分享系列文章的第三篇。本文涉及的技術細節是:基於CoreText的排版引擎。
CoreText概述
因為猿題庫的做題和解析介面需要複雜的排版,所以我們基於CoreText實現了自己的富文字排版引擎。我們的排版引擎對公式、圖片和連結有著良好支援,並且支援各種字型效果混排。對於內容中的圖片,支援點選檢視大圖功能,對於內容中的連結,支援點選操作。
下圖是我們應用的一個截圖,可以看到公式,圖片與文字混排良好。
對於富文字排版,除了可以用CoreText實現外,還可以用UIWebView實現。我以前寫過一篇介紹如何用UIWebView進行復雜內容顯示和互動的文章《關於UIWebView和PhoneGap的總結》,裡面介紹了使用UIWebView如何處理引數傳遞,同步與非同步等問題,感興趣的同學也可以翻看。
基於CoreText來實現和基於UIWebView來實現相比,前者有以下好處:
- CoreText佔用的記憶體更少,UIWebView佔用的記憶體更多。
- CoreText在渲染介面前就可以精確地獲得顯示內容的高度(只要有了CTFrame即可),而UIWebView只有渲染出內容後,才能獲得內容的高度(而且還需要用javascript程式碼來獲取)
- CoreText的CTFrame可以在後臺執行緒渲染,UIWebView的內容只能在主執行緒(UI執行緒)渲染。
- 基於CoreText可以做更好的原生互動效果,互動效果可以更細膩。而UIWebView的互動效果都是用javascript來實現的,在互動效果上會有一些卡頓存在。例如,在UIWebView下,一個簡單的按鈕按下效果,都無法做到原生按鈕的即時和細膩的按下效果。
當然基於CoreText的方案也有一些劣勢:
- CoreText渲染出來的內容不能像UIWebView那樣方便地支援內容的複製。
- 基於CoreText來排版,需要自己處理圖片排版相關的邏輯,也需要自己處理連結點選操作的支援。
我們最初的猿題庫行測第一版採用了基於UIWebView來實現,但是做出來發現一些小的互動細節無法做到精緻。所以後來的第二版我們就全部轉成用CoreText實現,雖然實現成本上增加了不少,但是應用的互動效果好多了。
使用CoreText也為我們後來的iPad版提供了技術積累,因為iPad版的頁面排版更加複雜,用UIWebView是完全無法完成相應的互動和排版需求的。
實現細節
服務端介面
我們在後臺實現了一個基於UBB 的富文字編譯器。使用UBB的原因是:
- UBB相對於HTML來說,雖然功能較簡單,但是能完全滿足我們對於富文字排版的需求。
- 做一個UBB的語法解析器比較簡單,便於我們將UBB渲染到各個平臺上。
為了簡化iOS端的實現,我們將UBB的語法解析在伺服器端完成。伺服器端提供了介面,可以直接獲得將UBB解析成類似HTML的檔案物件模型(DOM) 的樹型資料結構。有了這個樹型資料結構,iOS端渲染就簡單多了,無非就是遞迴遍歷樹型節點,將相關的內容轉換成 NSAttributeString即可,之後將NSAttrubiteString轉成CoreText的CTFrame即可用於介面的繪製。
支援圖文混排
支援圖文混排在教程:《Core Text Tutorial for iOS: Making a Magazine App》 中有介紹,我們在解析DOM樹遇到圖片節點時,則將該內容轉成一個空格,隨後設定該空格在繪製時,需要我們自己指定寬高相關資訊,而寬高資訊在圖片節點中都有提供。這樣,CoreText引擎在繪製時,就會把相關的圖片位置留空,之後我們將圖片非同步下來下來後,使用CoreGraph相關的API將圖片再畫在介面上,就實現了圖文混排功能。
下面的相關的示例程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|