作者:唐巧
打算分享一些有爭議的話題,並且表達一下我的看法。這是該系列的第二篇。
在本文中,我想討論的是:對於 UI 界面的編寫工作,到底應該用 xib/storyboard 完成,還是用手寫代碼來完成?
本著“使用過才有發言權”原則,我介紹一下我的經歷:
最早在網易開發 “ 有道雲筆記 ” 的時候,我們是使用 xib 來制作界面的。
三前年創業編寫“ 粉筆網 ”的時候,我也是使用 xib 來制作界面的。
之後開發“ 猿題庫 ”的時候,我嘗試了一下使用 storyboard 來制作界面,但最後放棄了。之後我把大部分界面編寫工作都改成由手寫代碼來完成。
在去年開發“ 小猿搜題 ”的時候,由於時間緊,我又再一次使用了 storyboard,但是我現在計劃將其用手寫代碼來重構一次。
xib 使用調研情況
除了我本人的經歷外,我也調研了一下我手機中裝的所有的 App 的開發情況,我寫了一個腳本,分析了我手機中一共 100 多個 App 包含的 xib 文件的個數。通常情況下一個 App 如果完全通過 xib/storyboard 來完成的話,那麼編寫包含的 xib 個數不應該少於 10 個(注:storyboard 在打包時會被拆解成多個它包含的 xib 文件)。
這個調研的最終結果,以及我分析用的腳本源碼在 這裡。我挑了一些比較有名的應用列在下面。(我另外也列出了它們包含的 js 的文件數量,這個可以反應出該應用對基於 UIWebView 的 Hybrid 編程的使用情況,不過與本次討論主題無關。)
以上這個表格說明了即使是比較著名的 App,在使用 xib/storyboard 上,也有很大的差異。舉幾個例子:
QQ、WeChat(微信)和易信同屬於社交類應用,而且按理說,由於用戶量和開發時間更長,QQ 和微信應該比易信更加復雜,但是從 xib 數量上,前者 xib 的數量都非常少。這說明,在 QQ 和微信中,很多界面肯定是通過手寫代碼來完成的。
滴滴打車、快的打車和易到用車同屬於叫車軟件,按理說滴滴打車、快的打車同時包含叫出租車和叫專車功能,應該比易到用車功能更多,更復雜。但是前者 xib 的數量都非常少。這也說明,滴滴打車、快的打車的界面很多是通過手寫代碼來完成的。
另外,像 Mailbox、播客 (Podcast)、Twitter、objcio 這些 App 中 xib 的數量為 0,說明其完全是用手寫代碼來完成 UI 界面編寫的。
當然,也有一些能看出來幾乎是由 xib 構成的應用,例如大眾點評、美圖秀秀、網易有道詞典。而蘋果的 iMovie 使用了 4000 多個 xib,真讓人不敢相信。我後來仔細看了一下,原來是因為 iMovie 做了國際化,每種語言大概有 120 個 xib,因為支持了將近 40 個語言,所以 xib 數量變成了 4000 多個。大眾點評的每個 xib 也被切分成了 4 個,具體用處我還沒研究,如下是一個示例:
./Payload/DPScope.app/WEDHotelShopInfoMainModule.nib ./Payload/DPScope.app/WEDHotelShopInfoMainModule.nib/objects-8.0+.nib ./Payload/DPScope.app/WEDHotelShopInfoMainModule.nib/objects.nib ./Payload/DPScope.app/WEDHotelShopInfoMainModule.nib/runtime.nib
討論
就上面的調研我們就可以看出,其實大家對於是否應該使用 xib 做界面是有爭議的。在實際案例中:
既有像 Twitter,Mailbox,objcio 這樣完全不使用 xib 做界面的情況。
也有像 QQ、微信、滴滴打車、網易新聞、猿題庫這樣少量使用 xib 的情況。
也有像支付寶、大眾點評這樣重度使用 xib 的情況。
那麼我就從我的角度把用與不用 xib 的優缺點表達一下。
使用 xib 和 storyboard 的優點
開發界面所見即所得,可以快速通過拖拽構造界面。
你可以從 storyboard 中很方便地梳理出所有View Controller的界面間的調用關系。這一點對於新加入項目組的開發同事來說,比較友好。
使用 Storyboard 可以使用Table View Controller的 Static Cell 功能。對於開發一些 Cell 不多,但每個 Cell 都不一樣的列表類設置界面會比較方便。
通過實現 – (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 方法,每個 View Controller 的跳轉邏輯都聚集在一處,這方便我們統一管理界面跳轉和傳遞數據。
Storyboard 可以方便將一些常用功能模塊化和復用。例如 WWDC2011 年介紹 Storyboard 的視頻就將微博分享功能模塊化成一個單獨的 Storyboard。
使用 xib 和 storyboard 的缺點
xib 對版本管理是災難。storyboard 實際上的多個 xib 的集合,所以更容易讓多人編輯產生沖突。而雖然它們是 xml 格式,但是沖突解決起來還是不如代碼那麼容易。
蘋果對 xib, storyboard 的設計中帶有當前電腦的操作系統版本和 Xcode 版本。所以如果兩個協作的開發者電腦操作系統或 Xcode 有不一樣的話,每次打開必定會修改這個文件。另外即使操作系統版本和 Xcode 版本一樣,有些時候打開看也會造成一些自動的修改。
storyboard 帶來的 segue 的概念對於開發來說並不省事,特別是在需要傳遞參數的時候。如果是用程序內部 trigger 一個 segue,那麼需要在另一個回調的地方設置 dest view controller 的參數信息。
我們發現 xib 中設置的顏色值並不精確,RGB 在真機 / 模擬器上常常會有 10 多像素的偏差。
xib 和 storyboard 對繼承的支持並不友好。無法做界面的繼承。
xib 和 storyboard 對搜索支持並不友好,無法方便地在 Xcode 中查找關鍵詞(但是可以通過寫 bash 命令來查找)。
storyboard 對組合支持得不太好,不允許在一個 xib 中附帶多個子 view。
xib 和 storyboard 不太方便做界面的模塊化管理,比如我們想統一修改界面中所有按鈕的字體樣式,那麼在 xib 和 storyboard 只能一個一個手工修改,而如果是代碼編寫的,則只需要改一個工廠方法的實現即可。
對於復雜的 App,storyboard 的性能會比較差。
關於手寫 UI 界面的一些挑戰
所以我更喜歡用代碼編寫 UI 界面,加上現在移動開發對於 App 要求的需求越來越強烈,很多復雜的交互效果需要在代碼中編寫,這種情況下 xib 能提供的幫助越來越有限。
但是 xib 提供的 “所見即所得” 這種優勢還是巨大的,如果我們是手寫界面,那麼調試起來是非常痛苦的。在這一裡,我給大家推薦購買 Reveal 這個界面調試工具,Reveal 可以在 App 運行時動態地修改界面元素的參數,這樣我們就可以一次性在代碼中把界面元素的字體、顏色、位置這些參數在 Reveal 調試好,避免多次重啟運行來調試界面。我在我的 《iOS 開發進階》 書裡,也花了一整章來介紹 Reveal 的使用。如下是書中的一個 Reveal 運行時截圖:
總結
其實,你完全不需要做一個 “艱難的決定”,你可以像 QQ 和微信那樣,根據具體情況來選擇性的使用 xib 和 storyboard。這裡有我的一些建議:
對於復雜的、動態生成的界面,建議使用手工編寫界面。
對於需要統一風格的按鈕或UI控件,建議使用手工用代碼來構造。方便之後的修改和復用。
對於需要有繼承或組合關系的 UIView 類或 UIViewController 類,建議用代碼手工編寫界面。
對於那些簡單的、靜態的、非核心功能界面,可以考慮使用 xib 或 storyboard 來完成。
對於很多新手來說,他們接觸到的都是使用 Interface Builder 來構造界面。希望本文讓大家了解到 xib 和 storyboard 在開發中的爭議,手寫界面並不是一個小眾的行為並且有很多好處,希望每一個人都能掌握它,並且在需要的時候根據具體情況來決定是否采用。