这是我最近一年在做的项目,用我们老大的话说,就是“能不能弄一个东西,让我的 iOS 程序一行代码不用改,却能运行在 Android 上”。为了这个目标,我们最后弄出了个这样的东西。
说起来我们之所以要做这个东西也是蛮有趣的。事情的起因,我们需要把一个为 iOS 写的排版引擎移植到 Android 上。但我们觉得这个排版引擎实在是太复杂了,而且把一个写好的 iOS 程序重新写个 Android 版本很无趣,那就变成了跟抄作业一样把 Objective-C 代码换成 Java 代码的行为了。
于是,为了移植这个排版引擎,我们面临两个选择:
把排版引擎移植到 Android
把 iOS 移植到 Android,不改排版引擎,直接在 Android 上跑
最终,我们选择了 2,于是我今后的一年(至今)就在搞这个东西了。
谈谈我个人的体会吧。我参与到这个项目之后,就真正体会到了 iOS 的博大精深。我之前当然知道 iOS 一定有很多很多东西,但是当真正参与了这个项目,才发现 iOS 居然是如此的庞大。以至于它的一个小小的方面居然就包含了那么多东西。
我本人的工作主要是把 Cocoa Touch 层移植到 Android 上去。具体就是如图:
把最上面那个青蓝色的方块移植到 Android 上去。顺便一提,iOS 的很多库是和 Mac 共用的。Apple 会用开源项目,Apple 自己闭源的东西会被别人开源。因此,如果是有历史的库,而且和 Mac 共用的库,一般都有开源项目可利用。但是 Cocoa Touch 层就比较坑爹,几乎没有可用的开源项目可直接使用。
于是,我本人的工作就是,手写 Cocoa Touch 层的代码,这个工作花了大概一年的时间。
某种意义上,我的任务性质有点像逆向推导出 Cocoa Touch 的内容。我需要查阅 Apple 的 API 文档,对文档的阅读要到细致到每个单词。然后给 h 文件填充实现,实现内容和 Apple 的程序员的实现越接近越好。但有一件事是 Apple 的程序员绝对不会做但我会做的,我还需要通过 JNI 调用 Android 的 API,并用 Java 编写一些功能让 Objective-C 使用。总之,至少在 Cocoa Touch 层这里,我要骗目标代码说它是在 iOS 上运行,而不能让它发现其实它是在 Android 上运行。
这个工作最麻烦的地方其实并不是在于“写出一个 Cocoa Touch 层”。光是写个 Cocoa Touch 是很简单的。难点在于,我手头能拿到的只有 Apple 的 API 文档以及和 h 文件。但是 API 文档给出的细节并不充足,这也可以理解,因为 API 文档是给开发 iOS 的开发者看的,可不是给我这种人看的。
因此,令人头疼的地方在于,针对具体实现,很多状态是隐藏的,也没有必要让 iOS 开发者知道这些状态,因此这些细节也绝对别想在 Apple 的 API 文档里找到。但是我必须知道这些细节,如果不知道这些细节,或者我自己写个实现有偏差的东西,到了 Android 上跑后会看到巨大的差异,而且这种差异极其难以定位。我这么说可能难以理解(恕我表达能力有限),总之就是“差之毫厘谬以千里”这样子。
这种定位的困难如果处理不当,对进度影响是很恶劣的。因为 bug 出现的地方可能和实际暴露的点之间隔了好多层呢。可能涉及到排版引擎的代码、各种开源项目的代码、我本人写的代码等。你要把 bug 和出问题的地方联系起来,不把整个项目拆了是做不到的。这种事情出一次,你也许得浪费 3、4 天时间来收拾。
而且更棘手的地方在于,如果你处理不好,这种现象可能每天都会冒出来。如果连续出个10几个,你就只能自杀了。幸运的是,我真的有认真考虑过这些可能性,并作了一些措施,结果,这一年里这种事情只出过几次。(但这几次就够呛了。)
这种问题经过我摸索,基本上靠两种方法解决。
第一,建立假设模型,然后实验。通过实验结果获取反馈,或者修改模型,或者证实模型。模型一旦证实,就可以开始码代码了。
第二,做实验可以获得大部分细节,但是某些太细节的东西做实验也没法活的。就只好先实现一个版本,然后假设它没有太大问题,等到之后证实有问题再改。
后一种情况比较坑爹,有些问题需要 3 个月才能暴露。将 3 个月后出现的问题与 3 个月之前写的代码联系起来是一件很头疼的事情。好在我 git 操作还算熟练。
对比起之前在另一家公司写业务逻辑代码的 Debug 过程,简直不要太轻松。有强大的 IDE,加上仅仅通过设置断点和打印日志就能发现 bug,简直太美好了。
现在,我们的排版引擎已经能顺利在 Android 上运行了。
你能想象,你用 MacBook 接上一台 Android 平板和一台 iPad,然后在 Xcode 按一个按钮,你的 Android 平板和 iPad 会同时打开一个相同的 App。目前我们就能达到这种程度。
不过很遗憾的是,我们的团队恐怕过几个月后就要解散了。虽然这个项目还有很多工作可以继续做,但是我们的团队恐怕不会继续做它了。以后可能会把它开源吧。