首先這是一個中斷的項目(雖然以后個人可能會繼續,但在公司層面上已經到此為止了),但是還是完成了相關的內容:
讀取rtf/rtfd文件,編輯(字體,大小,顏色),添加圖片,保存。
(至於為什么要選擇rtf格式來實現富文本編輯,下面會做說明)
在項目過程中還是遇到不小的問題,得到些許收獲,因此在這一並紀錄下來。
2012-02-06 16:04:07
首先我們得了解RTF是種什么格式,這個可以到微軟的網站上取找,或者搜索 “RTFV1.7規范.doc”。
規范里面主要是一些控制字,關鍵字之類的東西,我們需要對一些常見的字符進行解析以保證可以顯示大多數格式的rtf文件。
在之前的日志里,我提到了OmniGroup的三大類,這里再說明一下:
<OmniUI/OUIRTFReader.h>:讀取rtf/rtfd文件,得到NSAttributedString對象(iOS可以使用CoreText繪制NSAttributedString)
<OmniUI/OUIEditableFrame.h>:將NSAttributedString對象繪制到View,並實現編輯功能(主要實現iOS的相關delegate,如UIKeyInput,UITextInputTraits,EditMenu等)
<OmniUI/OUIRTFWriter.h>:將NSAttributedString對象 保存程文件rtf/rtfd,並且在Mac上可以打開。
這里先提一下,微軟的rtf標准里面是包含如何處理圖片的,但是在Mac上,如果包含圖片的rtf則會保存成rtfd格式。也就是說Mac上沒有完全支持RTF標准,而這主要是圖片部分沒有支持。
RTFD其實是bundle,本質上是一個文件夾,但是以一個對象的方式呈現在用戶面前。通常,rtfd包含一個“TXT.rtf”和圖片文件。
其中“TXT.rtf"包含如下內容:
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf260
{\fonttbl\f0\fswiss\fcharset0 ArialMT;\f1\fswiss\fcharset0 Helvetica;\f2\fnil\fcharset134 STHeitiSC-Light;
}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh7200\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f0\fs48 \cf0 1\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f1\fs24 \cf0 {{\NeXTGraphic iPadAppIcon.png \width1440 \height1440
}¬}\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f2\fs48 \cf0 \
}
其中,圖片關鍵字為 NeXTGraphic。
因此我們需要修改Reader/Writer,增加NeXTGraphic的解析。
所幸Omni對rtf常見的關鍵字已經做了很好的支持,所以這里的工作量減小很多。
1Reader修改:
添加了rtfd文件路徑變量,因為我們需要通過路徑來獲得圖片數據;
在- (void)_parseKeyword種添加NeXTGraphic的解析。
解析的過程模仿Omni的代碼即可,稍微需要注意的是圖片是作為OATextAttachment對象存儲,然后作為
OAAttachmentAttributeName屬性的值添加到最終的NSAttributedString中。
這部分可以參見Omni提供的TextEdit例子來查看。
2Writer修改:
同樣需要添加文件的路徑;
獲取OAAttachmentAttributeName屬性值,從中獲取圖片的原始數據和名字。將圖片寫入磁盤,將名字添加進”TXT.rtf“,然后再保存。
這部分也是依葫蘆畫瓢。
3OUIEditableFrame這部分沒有做太多更改,可以根據實際需要擴充
4RTF的編輯功能:
這一版本添加了style的選取,即在某處選中Style后彈出一個頁面,可以選擇字體和大小,完成后返回。然后輸入的字符是之前選擇的類型。
因為OUIEditableFrame有相應的獲取當前字符位置的接口,這一部分都放在個人的代碼里實現。
5cut/copy/paste:
主要是包含圖片的cut/copy/paste.
實現OUIEditableFrame delegate方法,因為UIPasteboard只能保存plist類型的數據,所以我把選中的文本存儲成一個臨時的rtfd文件,
然后paste的時候去從這個文件中讀取還原成NSAttributedString對象。
6 其他:
OUIEditableFrame是添加到UIScrollView上,這樣在編輯的時候也能自由滑動。Omni的例子是沒有這個功能,但是在編輯的時候會自動將
鍵盤下的文字適時的顯示出來。
還有就是修改完依賴庫以后先選取相應的schema在device上build一下,否則在編譯的時候你使用的庫還是之前的。
以上就是這個項目中個人認為重要的地方。其實Omni這個庫很強大但是不太好理解,因為文檔少,可以求助的地方不多,所以遠不如Three20有群眾基礎。
就單單將他的例子模仿學會也着實花了不少時間,研究代碼的時候會很痛苦但是理清了思路后就有豁然開朗的感覺,尤其是發現Omni寫的非常模塊化,非常容易擴展和自定義。
但是也有很多地方未搞明白,比如提供例子里的App入口函數沒有找到,以及如何使用他聞名的內存查看功能等等。
另外還有一個問題:
在生成Ad Hoc版本的ipa時,始終沒有結果。Xcode顯示成功了,但是沒有生成archive。網上搜了些方法,還是無果。如果有知道的朋友,麻煩請賜教。
接下來談談這個項目本身:
當時公司是想在某一個App上添加文檔編輯功能,目標是生成的文件在Mac/iOS/Windows上通用,並且可以編輯,改變字體大小,添加圖片。
因為App本身是免費的,希望這個功能以簡單的方式實現。
於是目光落在了RTF身上。
但是沒有想到RTF編輯器的水相當深,在我搜索資料的過程中,發現即使是windows開發人員都覺得是件麻煩事。
於是,公司最終以帶圖片的RTF不能在上述平台上通用而中斷項目。
2012-02-07 09:03:41
個人的思考:
1前期調查的時候,就發現相關的資源不多,而且有富文本編輯功能的往往都是以此作為賣點的收費App,沒有哪個App免費的提供了這個功能。
evernote在某種程度上也是富文本編輯,但是其文件格式是自定義的,只能用evernote打開
2作為一個免費App,富文本編輯功能絕對是亮點,但是考慮到難度(因為只有我一個人負責開發),可以迭代式的完善功能。
比方說,先實現文字的富文本編輯,隨后升級成可以添加圖片,再添加存儲的文件在個平台通用等特性
3windows無法正確識別RTFD,那么我們可以設置導出某種格式的功能,比如html等等
以上是個人對做項目的思考。