Using Omni to do RTF Editor

首先这是一个中断的项目(虽然以后个人可能会继续,但在公司层面上已经到此为止了),但是还是完成了相关的内容:

读取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等等

 以上是个人对做项目的思考。

 

 

 

 

posted on 2012-02-07 09:15  scorpiozj  阅读(2891)  评论(5编辑  收藏  举报