- 原文地址:Life without Interface Builder
- 原文做者:Zeplin
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:Ryden Sun
- 校對者:talisk allenlongbaobao
在過去的幾個月,在 Zeplin 的 macOS 版本 app 中,咱們開始在開發一些新的功能時,不使用 Interface Builder 或者 Storyboards。前端
在 iOS/macOS 社區,這是一個很具備爭議性的話題,而且做爲一個以前極其依賴 Interface Builder 的團隊,咱們想用一些真實的案例,來分享一下咱們爲何作了這個轉換。即使這篇文章是從 macOS 方面出發的,但其中我提到的任何東西均可以被應用到 iOS 上。android
在用了兩年的 Objective-C 後, Zeplin 在 2015 年底,第一次用 Swift 來編寫其中一個模塊。從那之後,咱們一直使用 Swfit 開發新的功能而且逐漸地遷移以前存在的部分。目前,macOS 版本的 app,有 75% 是用 Swift 編寫的。ios
有趣的是,在咱們剛開始用 Swift 時,就開始考慮放棄 Interface Builder。git
在 Swift 中使用 Interface Builder 會帶來不少 optional(Swift 中的可選類型),並且它們都不屬於類型安全的域。我也不是僅僅在討論 outlets,若是你在 Storyboards 中使用 segues,你的數據模型中的 property 也會變成可選類型。事情就是在這裏變得不受控制。你的 view controller 是要求 property 正常工做的,如今它們變成了 optional,你就開始處處寫 guard
,開始變得混亂,考慮在哪裏可以優雅地處理它們,哪裏能簡單地從 fatalError
中逃脫出來。這是很容易出錯的,並且會明顯地下降代碼的可讀性。github
你的 view controller 是要求 property 正常工做的,如今它們變成了 optionals,你就開始處處寫
guard
。後端
……除非你使用 Implicitly Unwrapped Optionals(隱式解析可選),使用操做符!
。這在大多數時候是有用的,不會出現任何問題,但這樣感受是在欺騙 Swift 平臺。咱們大多數人相信,Implicitly Unwrapped Optionals 應該在極少數的場景下使用,並且在平常開發中是應該避免在 Storyboards 中使用。安全
在 Objective-C 寫佈局代碼還不算太糟,可是使用 Swift 就變得更簡單了,而且最重要的是,更易讀。聲明 Auto Layout 的 constraints 很輕鬆也很漂亮,這要感謝像 Cartography 這樣的庫。bash
// 建立 property 時定義外觀表現
let editButton: NSButton = {
let button = NSButton()
button.bordered = false
button.setButtonType(.MomentaryChange)
button.image = NSImage(named: "icEdit")
button.alternateImage = NSImage(named: "icEditSelected")
return button
}()
…
// 用 Cartography 聲明 Auto Layout 限制
constrain(view, editButton, self) { view, editButton, superview in
editButton.left == view.right
editButton.right <= superview.right - View.margin
editButton.centerY == view.centerY
}
複製代碼
我猜測,咱們能夠將使用 Interface Builder 的開發者分爲兩種類型:一類是隻用來作 Auto Layout 和 segues 的,一類是也會用來附加設計的;在 Interface Builder 設置顏色,字體和其餘可視化的屬性。app
在使用 Interface Builder 時,你會發現你本身在複製粘貼你以前寫好的視圖 —— 而且你都不會對這種行爲感到很差。佈局
咱們 稍稍微地 屬於第二種類型 !Zeplin 是一個常變的 app,當只有設計元素改變的時候,這最終就開始困擾咱們了。讓咱們假設,你只須要改變一個公用按鈕的背景顏色。你須要打開每個 nib 文件而且手動的改變它們。當這個須要常常重複的時候,你就會可能漏掉一些。
當你使用純代碼來編寫視圖時,這會激勵你複用代碼。正相反,在使用 Interface Builder 時,你會發現你本身在複製粘貼你以前寫好的視圖 —— 而且你都不會對這種行爲感到很差。
根據 Apple 的觀點,Storyboards 是將來。從 Xcode 8.3開始,咱們在開發項目的時候,都沒有一個能夠不使用 Storyboards 的選項。😅 這確實很使人傷心,這都沒有一個直接了當的方法來複用 Interface Builder 中的視圖。
這就是爲何,咱們發現本身一直用純代碼來編寫一些經常使用的公共視圖。建立一個能夠同時用代碼和 nib 初始化的視圖也是棘手的,強制你去實現兩個構造器而且去作一樣的初始化行爲。當你只是用代碼時,你能夠安全的忽略 _init?(coder: NSCoder)_
。
在轉換以後,咱們有了一個認知:使用代碼構建界面提高了咱們對於 UIKit
和 AppKit
組件的理解。
咱們在轉換一些以前用 nib 實現的舊的功能。當咱們嘗試去保留外觀,咱們必須去學習更多的關於不一樣的屬性在作什麼和他們是如何影響一個組建的外觀。在以前,他們只是被 Interface Builder 默認設置的一些選擇和複選框,並且它們就這樣起做用了。
使用代碼構建界面提高了咱們對於
UIKit
和AppKit
組件的理解。
對於導航性的組件,像 UINavigationController
,UITabBarController
,NSSplitViewController
這些都是可行的。尤爲對於新手來講,他們極其依賴於這些組件但又不是真正地理解它們在幕後是怎麼工做的。當你嘗試用代碼來初始化和使用它們時,就會當即感受很舒服。
Zo 在打開一個龐大的 Storyboard 時很煎熬。
是否曾有過一個 bug,你花費幾分鐘時間來追溯而且最終發現,形成它的緣由是一個沒有被鏈接起來的 outlet 或者是 nib 中一個你無心中改變的選項?
每個你用代碼建立的組件都會被包在一個單獨的源文件,所以你不須要去擔憂在 nib 和源文件之間的跳轉。這會幫助咱們在調試問題是更迅速,而且一開始就會引入更少的 bug。
爲了讀懂和理解透徹 nib,你要不得是一個 nib 奇才,要不你就得花費至關多的時間!這就是爲何**大多時間,人們都直接在審覈代碼時略過 nib 的改動,由於它太嚇人了。**想想這些潛在的可視的 bug 可能會由於在代碼中使用常量和文字直接被消除掉。
在反對 nib 的聲音中,衝突的合併是你會最常常聽到的抱怨。若是你曾在一個使用 nib,尤爲是 Storyboards 的項目中工做過,你可能也親身經歷過。你知道這一般意味着:一我的的工做會須要被回滾而後再重應用。這些事最使人煩躁的衝突,並且當你團隊變大時,會變得愈來愈讓人沮喪。你能夠相應地分配任務,這在大多數時候能夠克服這個問題。但在 Storyboards,即便在你單獨寫一個 ViewController 時,這樣的問題均可能發生。
出人意料的,當時這對於 Zepin 來講,不算是個問題 —— 由於咱們是一個比較小的團隊,我猜。這也是爲何我把這一點放到了最後來講。
我已經列出了不少的緣由來解釋爲何中止使用 Interface Builder 是一個好主意,但別誤會,有一些用例下,使用 Interface Builder 也是有道理的。即便咱們故意省略這些用例,由於咱們目前,在沒有 Interface Builder 的狀況下更加開心了。
不要懼怕去實踐,而且去看看這是否也適合大家的工做流程!
感謝咱們可愛的 @ygtyurtsever。讓咱們知道你是怎麼想的,在下面留言吧!👋
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。