Swift 程式碼教學:好好設定物件 讓程式碼更簡潔清晰


本篇原文(標題:如何讓 iOS 程式碼更美觀:物件的設定)刊登於作者 Medium,由 Li-Heng Hsu 所著並授權轉載。

我們都看過這樣的 code:

簡單、明瞭,但當中卻有些問題,讓這段 code 不是那麼的好看。

甚麼問題呢?

  1. textField 這個詞重複出現了五次。
  2. 整段程式碼沒有階層,只能靠 comment 與空行去跟其它的程式碼做區隔。

這整段程式碼做的其實是語意上相關聯的一組事件。如果我們用白話來解釋的話,就是:

我要在我的 view 底下加一個新的、經過設定的 text field。

如果我們直接把它轉譯成 Swift 語法的話,概念上大概會變成這樣:

雖然看起來很簡單,但實際上要實作的話,就得要去寫 convenience init 才行:

這樣多麻煩啊?何況還可能會有更多的 property 可以設定。然而,不想要寫 init 的話,就沒辦法用 parameter list 去寫設定了。

另一個常見的方法,是寫一個無名的 function(也就是一個 closure)來當作 factory,去製造出所要的物件:

這種方法讓階層出來了,我們可以很清楚地看到整段 code 就是在做兩件事:設定 textFieldaddSubview。這個方法雖然比一開始還多了三行,但它讓整個程式碼的架構更清楚易懂、更容易整理,已經算是進步了。再者,它也不需要另外寫 init 或 function,增加的程式碼其實不算多。更甚者,它還可以這樣用:

如此一來,我們就可以把大量的程式碼從 viewDidLoad 裡面移走,還他一個乾淨。

可是,我們還是沒有解決一個問題:它的重複性太高了。看看上面那段程式碼,光是 textField 就出現了 7 次,UITextField 也出現了兩次。有什麼辦法可以減少它的重複性呢?

有的。我們先想想看把重複的東西都拿掉之後,它應該變成什麼樣子:

也就是說,接近我們的第一個解決方法:寫一個 convenience init。然而,這個做法的缺點就是要把要設定的東西一項一項寫在 init 裡面,太麻煩了。這樣的話,有沒有辦法不用把要設定的東西都寫出來呢?有的,我們可以用 closure 來達到類似的效果:

然後我們就可以:

這樣是不是就解決了我們一開始列出的兩個問題了呢?我們既把設定 textField 的 code 放在同一個 block 裡面,也用 $0 去取代 textField,讓程式碼更簡潔好看。

然而,我們還是得針對每個 class 都去寫它的 convenience init,因為它的 configureHandler 所接收的類型都不同。即使我們這樣寫:

我們也會需要在實際使用的時候去 downcast,像這樣:

這樣好像又回到用無名 function 的方法了。不過還好,我們還有 generic 這個 Swift 的秘密武器,可以用 Self 去代表自己的型別。只是 ⋯⋯ class 本身並不支援使用 Self,只有 protocol 可以。

那沒關係,我們就用 protocol 來寫吧:

注意到玄機了嗎?這個 Declarative protocol 什麼需求都沒有,只有在 extension 裡面才有東西。也就是說,這個 protocol 不是拿來當介面使用的(如 UITableViewDataSource 之類的東西),而是拿來幫既有的 class 加 function 用的。

簡單來說,我們把剛剛寫在 NSObject 的 extension 的 convenience init 整個搬到一個 protocol 的 extension 裡面,再讓 NSObject 去遵從 (conform) 這個 protocol。如此一來,我們就可以使用 Self 了。

之所以用 NSObject,是因為這樣的設定法幾乎只有 class 才用得到,而在 UIKit 底下,所有的 class 都繼承自 NSObject。不過,我們也可以用另一種「更 Swift」的寫法:

如此一來,即使自訂的、非繼承自 NSObject 的 class 也可以使用這個 convenience init 了。

那麼,實際寫出來是什麼樣子的呢?

是不是讓程式碼變得簡潔許多,架構也更清楚了呢?

本篇原文(標題:如何讓 iOS 程式碼更美觀:物件的設定)刊登於作者 Medium,由 Li-Heng Hsu 所著並授權轉載。
作者簡介:Li-Heng Hsu,iOS 開發者、寫作者、filmmaker。現正負責開發 Storyboards by narrativesaw 此一故事板文件 app 中。深深認同 Swift 對於程式碼易讀性的重視。個人網站:lihenghsu.com。電郵:[email protected]

此文章為客座或轉載文章,由作者授權刊登,AppCoda編輯團隊編輯。有關文章詳情,請參考文首或文末的簡介。

blog comments powered by Disqus
訂閲電子報

訂閲電子報

AppCoda致力於發佈優質iOS程式教學,你不必每天上站,輸入你的電子郵件地址訂閱網站的最新教學文章。每當有新文章發佈,我們會使用電子郵件通知你。

已收你的指示。請你檢查你的電郵,我們已寄出一封認證信,點擊信中鏈結才算完成訂閱。

Shares
Share This