為什麼我要編寫自己的UIKit

weakish發表於2014-03-14

如今的軟體更像是由不計其數的磚塊堆砌起來的金字塔,沒有一點結構完整性,完全是成千上萬的奴隸依靠蠻力修建起來。

-- 艾倫·凱伊(Alan Kay)

這是一個關於(Web)網際網路的故事。根據很多定義,它是這個星球上出現的偉大奇蹟之一,它有一個低調的開始,僅僅作為傳送超文字檔案的一種媒介,但是當它遇上了Javascript 這門指令碼語言,它變成了一個可以創造成千上萬應用的卓越平臺。

時光前進二十年如今你已經擁有多家價值數十億美金的公司(從Facebook到LinkedIn),你投入數不清的開發工程師資源想用HTML來打造一款高水準的應用,我的公司(bubbli)也陷入了類似的陷阱。人們總是說“多用CSS transforms”“用Google Closure Tool優化程式碼”,可這完全是個傻瓜才會乾的差事,這樣做所跨越的抽象層次太深,就好像建一所空中樓閣一樣。

最後我們終於醒悟過來,開始為每一個平臺開發原生應用,因為每個平臺都提供了“最好的工具”,這些開發工具就是被設計用來從零開始來建立應用。而且,移動平臺的計算能力在過去幾年得到了飛速發展:Apple和Google持續地在對應的平臺上推出各種新技術。我還記得在WWDC 2013的開發者講座中聽過的一次UI Dynamics主題的課程,我對自己說:

WOW,太不可思議了!

緊接著是:

等一下,為什麼我們需要Apple這種填鴨式的UI創新?難道我們忘記了計算機是一種圖靈完備的裝置,我們可以讓它做任何我們想做的事?

就這樣我掉進了兔子洞裡面,開始著手用OpenGL ES重寫我自己的UIKit。

大白兔

提示:我關閉了文字渲染,因為我在不同的平臺使用了不同的文字渲染庫,在我錄製這幅GIF時我還沒有完成在OS X上的文字測試。不過在iOS上效果看起來還不賴。

如果你從未用過我們的應用,給你一些提示:這些球型的照片叫做氣泡,你可以用你的iPhone想鏡子一樣觀察周圍的世界。

我們可以把它們想象成一種通向自身的一種媒介,延續它們自生的視角。就像你從未看過由幾千張圖片構成的電影,你也不會看到一個氣泡平展成一幅平面圖片。

這裡的難處在於繪製氣泡的資料量要比一幅平面照片而言多得多,在60幀下要讓照片生成非線性的樣式還要面對CPU的效能限制。一開始我想用CoreAnimation來實現,但之前做Facebook Page的哥們發現這樣的效率不夠,在UIKit下併發載入很多資源非常困難。很快我決定使用OpenGL來繪製氣泡。

掉下兔子洞

此刻最大的挑戰是OpenGL對於CoreAnimation生成的動畫不夠友好。我設法混合了UICollectionViews和一些OpenGL程式碼,已經接近我們預期的效果,但在WWDC上看到了iOS 7的改變後,我們決定增加照片的數量,並且動畫的變換應該能夠承上啟下,圍繞這個精神我們迅速構思新的互動形式.一件讓我們很痛苦的事情是如何在持續改變氣泡檢視尺寸的同時不會在氣泡間產生縫隙,這種效果給人感覺就像整個介面向左邊收縮

隨著你的手指向左滑動,整個網格檢視就像一條繩索沿著一個竹竿纏繞的越來越緊。

這張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/ifdef語句。

別再等待你所依賴的閉源框架的修復

CoreData上下文在合併兩個上下文時會觸發數百萬的KVO通知嗎?當然不會。當你從零開始建造整個世界時,你可以僅憑蠻力和堅持不懈來解決任何Bug。對比你在IE11裡發現的種種神奇狀況,耐心等看看明年是不是還是這尿性。

而且我敢打賭,有能力的開發人員編寫自己的框架比使用別人的框架容易地多,因為你非常清楚所有的東西如何工作,只要你能建立比較好的抽象,其實只是幾千行程式碼的問題。

壓榨當代硬體的變態效能

事實上每一個與螢幕連線的CPU都配有一個GPU晶片。那我們為何還要在CPU上做如此多的繪畫工作?越來越多的消費者希望得到沉浸式的體驗,GPU在此方面可以提供高效的計算能力。你可以看看在我們的應用的最下方那個相機按鈕,你會注意到當你滑動螢幕時它會折射螢幕的其他位置.iOS 7極大地改善了螢幕截圖的效能,但是和一個用紋理渲染的檢視沒有什麼可比性。

統一的程式碼庫

不久的未來我們將不用擔心在不同的平臺上實現相同功能的困擾。如果我對Go語言不感冒,我可能會使用app中用到的資料庫抽象/程式碼來編寫我們的後端,這樣做最顯而易見的好處就是定製化和有效控制開發隊伍的規模。

平臺大戰走向終結

這篇文章裡其實沒有什麼新東西——遊戲開發人員很多年前就認可了這種這種哲學。平臺廠商們使用小伎倆,試圖讓開發者相信使用者介面和他們所執行的作業系統是緊緊關聯的。不過,這些年來的趨勢改變了,你已經可以在沒有任何特殊許可權的使用者空間執行許多不可思議的程式碼,僅僅用POSIX和Kronos標準你就可以走得很遠。 此外最令我興奮的是,emscripten有潛力執行各種不同的平臺。如果emscripten能夠持續改善,JS會變得越來越不重要,在某個時間點瀏覽器廠商可以選擇一個不用編譯JS的後臺置換現有平臺,我們再也不用為我們的應用適配多種瀏覽器而感到煩惱了。 如果我是Apple或者Google,我會非常關心這樣的理念是否在推進,一個只專注於某個平臺的開發者將會失敗,市場份額會變得越來越流動。要不是我的公司不是Apple或Google,我投入所有可能的資源來推行這個理念。 Alan Kay經常評論說:“我們所感知到的現代軟體系統非常複雜,我們接受了這個‘事實’,然而其實這並不是事實。如果我們根據這麼多年來的經驗重寫所有的抽象,我們會得到一個大幅縮小的核心程式碼k庫。”我更傾向於他的這種看法,也非常激動想要看到如果我們都這麼做能帶來的創新。


原文 Why I wrote my own UIKit
翻譯 伯樂線上 - 袁欣
修訂 SegmentFault

相關文章