为什么我要重写自己的UIKit?

jopen 10年前

如今的软件更像是由不计其数的砖块堆砌起来的金字塔,没有一点结构完整性,完全是成千上万的奴隶依靠蛮力修建起来。 – 艾伦·凯伊(Alan Kay)

这是一个关于(Web)互联网的故事。根据很多定义,它是这个星球上出现的伟大奇迹之一,它有一个低调的开始,仅仅作为发送超文本文件的一种媒介,但是当它遇上了Javascript 这门脚本语言,它变成了一个可以创造成千上万应用的卓越平台。

时光前进二十年如今你已经拥有多家价值数十亿美金的公司(从非死book到LinkedIn),你投入数不清的开发工程师资源想用HTML来打造一款高水准的应用,我的公司(bubbli)也陷入了类似的陷阱。人们总是说“多用CSS transforms”“用Google Closure Tool优化代码”,可这完全是个傻瓜才会干的差事,这样做所跨越的抽象层次太深,就好像建一所空中楼阁一样。

最后我们终于醒悟过来,开始为每一个平台开发原生应用,因为每个平台都提供了“最好的工具”,这些开发工具就是被设计用来从零开始来创建应用。而 且,移动平台的计算能力在过去几年得到了飞速发展:Apple和Google持续的在对用的平台上推出各种新技术。我还记得在WWDC 2013的开发者讲座中听过的一次UI Dynamics主题的课程,我对自己说:

WOW,太不可思议了!

紧接着是:

等一下,为什么我们需要Apple这种填鸭式的UI创新?难道我们忘记了计算机是一种图灵完备的设备,我们可以让它做任何我们想做的事?

就这样我掉进了兔子洞里面,开始着手用OpenGL ES重写我自己的UIKit。

大白兔

为什么我要重写自己的UIKit?
提示:我关闭了文字渲染,因为我在不同的平台使用了不同的文字渲染库,在我录制这幅GIF时我还没有完成在OS X上的文字度量。不过在iOS上效果看起来还不赖。

如果你从未用过我们的应用,给你一些提示:这些球型的照片叫做气泡,你可以用你的iPhone想镜子一样观察周围的世界。

我们可以把它们想象成一种通向自身的一种媒介,延续它们自生的视角。就像你从未看过由几千张图片构成的电影,你也不会看到一个气泡平展成一幅平面图片。

这里难处绘制气泡的数据量要比一幅平面照片而言多得多,在60帧下要让照片生成非线性的样式还要面对CPU的性能限制。一开始我想用 CoreAnimation来实现,但之前做非死book Page的哥们发现这样的效率不够,在UIKit下并发加载很多资源非常困难。很快我决定使用OpenGL来绘制气泡。

掉下兔子洞

此刻最大的挑战是OpenGL对于CoreAnimation生成的动画不够友好。我设法混合了UICollectionViews和一些 OpenGL代码,已经接近我们预期的效果,但在WWDC上看到了iOS 7的改变后,我们决定增加照片的数量,并且动画的变换应该能够承上启下,围绕这个精神我们迅速构思新的交互形式.一件让我们很痛苦的事情是如何在持续改变 气泡视图尺寸的同时不会在气泡间产生缝隙,这种效果给人感觉就像整个界面向左边收缩

为什么我要重写自己的UIKit?

 随着你的手指向左滑动,整个网格视图就像一条绳索沿着一个竹竿缠绕的越来越紧。

这张gif是在我的电脑上录制,所以这些气泡是静态的,在iPhone上每个气泡都会随着陀螺仪变换角度。看起来效果简直不可思议,这是个免费的应用, 你可以下载来看看这种效果。

我一直想用纯OpenGL来实现,让我惊讶的是,原来只要对UICollectionView进行高度优化也可以很容易在屏幕上显示几百个气泡,我看我只能给自己打个20分。

现在已经没有回头路了。

改写全部

在创业公司做仅有的一个程序员的最大好处就是我不需要跟别人解释我的想法是可行的。不过当我们要发布应用,Apple可不会让一款看起来带有明显iOS 6风格的应用上线,不管怎样我们还需要做iOS 7适配。所以我一不做二不休,用OpenGL ES从头开始重写一切东西。

为了以后的成工作准备,首先我要确保我能用最小的改动能让我写的东西运行在任何如今流行的平台上。我抛弃了CoreData转用sqlite,改用 C++ 11 而不用Objective-C写代码。我冲洗了我自己的网络栈,触摸处理,滚动视图,表视图,高斯模糊,资源加载,动画等等。

在WWDC和我们应用上线之间的四个多月我重写了应用所有代码,事实上加上我自己写的UIKit比我们之前的应用还少了几千行代码,上线后,尽管很紧张但是似乎没人发现我们的应用有任何不舒服的地方。


不只是小把戏

重写iOS 7的特效是一项有趣的实验,不过重写你自己的UIKit的真正回报是它在某种程度上实现了HTML 5 的承诺—一次编写,全平台运行,不会牺牲任何的性能和宝贵的开发时间。

迁移到其他平台?小Case

在圣诞节的周末我匆匆忙忙编写了一款Mac应用。事实上上面的截图都是这款应用所录制的而不是从iOS模拟器。我已经成功这款应用迁移到其他平台上了(好吧,Wondow Phone不在其中),甚至用emscripten迁移到浏览器中运行!迁移后会不会损失一些苹果的滑动特效?当然,不过不用担心只是一些if/fdef语句。

别再拖延修补你所依赖的闭源框架

CoreData上下文变量在合并两个上下文时会触发数百万的KVO通知吗?当然不会。当你从零开始建造整个世界时,你可以仅凭蛮力和坚持不懈来解决任何Bug。对比你在IE11里发现的种种神奇老Bug,耐心等看看明年是不是还是这尿性。

而且我敢打赌,有能力的开发人员重写自己的框架比使用别人的框架更有效率,因为你非常清楚所有的东西如何工作,只要你能建立比较好的抽象,其实只是几千行代码的问题。

压榨当代硬件的变态性能

事实上每一个与屏幕连接的CPU都配有一个GPU芯片。那我们为何还要在CPU上做如此多的绘画工作?越来越多的消费者希望得到沉浸式的体 验,GPU在此方面可以提供高效的计算能力。你可以看看在我们的应用的最下方那个相机按钮,你会注意到当你滑动屏幕时它会折射屏幕的其他位置.iOS 7极大地敢删了屏幕截图的性能,但是和一个用纹理渲染的视图没有什么可比性。

统一的代码库

不久的未来我们将不用担心在不同的平台上实现相同功能的困扰。如果我对Go语言不感冒,我可能会使用于前台相同的语言,这样做最显而易见的好处就是可以有效控制开发队伍的规模。

平台大战之后

这篇文章的观点其实没有什么新意可言—游戏开发人员很多年前就认可了这种这种哲学。平台厂商们刷的小伎俩,试图让开发者相信用户界面和他们所运行于 的操作系统是紧紧关联的。不过近些年来的趋势,你已经可以在没有任何特殊权限的用户控件运行不可思议的代码量,仅仅用 POSIX和Kronos接口你就 可以得到相当多的惊喜。此外最令我兴奋的是,在emscripten上有潜力能运行各种不同的平台。如果emscripten能够持续改善,JS会变得越 来越不重要,在某个时间点浏览器厂商可以选择一个不用编译JS的后台置换现有平台,我们再也不用为我们的应用适配多种浏览器而感到烦恼了。如果我是 Apple或者Google,我会非常关心这种哲学是否在进行之中,一个只专注于某个平台的开发者将会失败,这也会导致市场份额会变得更加不固定。如果我 的公司不是这样,我会愿意倾入所有可能的资源来推行这项哲学。Alan Kay经常评论说“我们所感知到的现代软件系统非常复杂,然而事实并非如此”,如果我们追溯过去所学重写所有的抽象,你会得到一个大幅缩小的核心代码。我 更倾向于他的这种看法,也非常激动想要看到由此带来的创新。

下期再会

后面我希望拓展来讲讲一些在搭建一个跨平台的UI框架时是开发更加有趣的一些关键抽象,和一些缺点和挑战。再次之前,请通过@newhouseb在推ter上找到我。

原文链接: Ben Newhouse   翻译: 伯乐在线 - 袁欣
译文链接: http://blog.jobbole.com/61414/