- 原文作者 : Kristian Andersen
- 译文出自 : 掘金翻譯計劃
- 译者 : Zheaoli
- 校對者: owenlyn, yifili09
不久之前,在我寫的好與壞,Swift 面面觀 Part1一文中,我介紹了一些關於在 Swift 裡怎樣去寫出優秀代碼的小技巧。在 Swift 發布到現在的兩年裡,我花費了很長時間去牢牢掌握最佳的實踐方法。欲知詳情,請看這篇文章:好與壞,Swift 面面觀 Part1.
在這個系列的文章中,我將嘗試提煉出我認為的 Swift 語言中好與不好的部分。唔,我也希望在未來有優秀的 Swift 來幫助我征服 Swift (唔,小夥子,別看了,中央已經決定是你了,快念兩句詩吧)。如果你有什麼想法,或者想告訴我一點作為開發者的人生經驗什麼的話,請在 Twitter 上聯繫我,我的賬號是 ksmandersen。
好了廢話不多說,讓我們開始今天的課程吧。
guard
大法好,入 guard
保平安#
在 Swift 2.0 中, Swift 新增了一組讓開發者有點陌生的特性。Guard
語句在進行防禦性編程的時候將會起到不小的作用。(譯者注 1:防禦性編程(Defensive programming)是防禦式設計的一種具體體現,它是為了保證,對程序的不可預見的使用,不會造成程序功能上的損壞。它可以被看作是為了減少或消除墨菲定律效力的想法。防禦式編程主要用於可能被濫用,惡作劇或無意地造成災難性影響的程序上。來源自 wiki 百科)。每個 Objective-C 開發者可能對防禦性編程都不陌生。通過使用這種技術,你可以預先確定你的代碼在處理不可預期的輸入數據時,不會發生異常。
Guard
語句允許你為接下來的代碼設定一些條件和規則,當然你也必須釘定當這些條件(或規則)不被滿足時要怎麼處理。另外,guard
語句必須要返回一個值。在早期的 Swift 編程中,你可能會使用 if-else
語句來對這些情況進行預先處理。但是如果你使用 guard
語句的話,編譯器會在你沒有考慮到某些情況時幫你對異常數據進行處理。
接下來的例子有點長,但是這是一個非常好的關於 guard
作用的實例。 didPressLogIn
函數在屏幕上的 button
被點擊時被調用。我們期望這個函數被調用時,如果程序產生了額外的請求時,不會產生額外的日誌。因此,我們需要提前對代碼進行一些處理。然後我們需要對日誌進行驗證。如果這個日誌不是我們所需要的,那麼我們不再需要發送這段日誌。但是更為重要的是,我們需要返回一段可執行語句來確保我們不會發送這段日誌。guard
將會在我們忘記返回的時候拋出異常。
@objc func didPressLogIn(sender: AnyObject?) {
guard !isPerformingLogIn else { return }
isPerformingLogIn = true
let email = contentView.formView.emailField.text
let password = contentView.formView.passwordField.text
guard validateAndShowError(email, password: password) else {
isPerformingLogIn = false
return
}
sendLogInRequest(email, password: password)
}
當 let
和 guard
配合使用的時候將會有奇效。下面這個例子中,我們將把請求的結果綁定到一個變量 user
,之後通過 finishSignUp
方法函數使用 (這個變量)。如果 result.okValue
為空,那麼 guard
將會產生作用,如果不為空的話,那麼這個值將對 user
進行賦值。我們通過利用 where
來對 guard
進行限制。
currentRequest?.getValue { [weak self] result in
guard let user = result.okValue where result.errorValue == nil else {
self?.showRequestError(result.errorValue)
self?.isPerformingSignUp = false
return
}
self?.finishSignUp(user)
}
講道理 guard
非常的強大。唔,如果你還沒有使用的話,那麼你真應該慎重考慮下了。
在使用 subviews
的時候,將聲明和配置同時進行。#
如前面一系列文章中所提到的,開發 view
的時候,我比較習慣於用代碼生成。因為對 view
的配置套路很熟悉,所以在出現佈局問題或者配置不當等問題時,我總是能很快的定位出錯的地方。
在開發過程中,我發現將不同的配置過程放在一起非常的重要。在我早期的 Swift 編程經歷中,我通常會聲明一個 configureView
函數,然後在初始化時將配置過程放在這裡。但是在 Swift 中我們可以利用 屬性聲明代碼塊 來配置 view
(其實我也不知道這玩意兒怎麼稱呼啦(逃)。
唔,下面這個例子裡,有一個包含兩個 subviews
、 bestTitleLabel
、 和 otherTitleLabel
的 AwesomeView
視圖。兩個 subviews
都在一個地方進行配置。我們將配置過程都整合在 configureView
方法中。因此,如果我想去改變一個 label
的 textColor
屬性,我很清楚的知道到哪裡去進行修改。
class AwesomeView: GenericView {
let bestTitleLabel = UILabel().then {
$0.textAlignment = .Center
$0.textColor = .purpleColor()
}
let otherTitleLabel = UILabel().then {
$0.textAlignment = .Center
$0.textColor = .greenColor()
}
override func configureView() {
super.configureView()
addSubview(bestTitleLabel)
addSubview(otherTitleLabel)
// Configure constraints
}
}
對於上面的代碼,我很不喜歡的就是在聲明 label
時所帶的類型標籤,然後在代碼塊裡進行初始化並返回值。通過使用 Then這個庫 ,我們可以進行一點微小的改進。你可以利用這個小函數去在你的項目裡將代碼塊與對象的聲明進行關聯。這樣可以減少重複聲明。
class AwesomeView: GenericView {
let bestTitleLabel = UILabel().then {
$0.textAlignment = .Center
$0.textColor = .purpleColor()
}
let otherTitleLabel = UILabel().then {
$0.textAlignment = .Center
$0.textColor = .greenColor()
}
override func configureView() {
super.configureView()
addSubview(bestTitleLabel)
addSubview(otherTitleLabel)
// Configure constraints
}
}
通過不同訪問級別來對類成員進行分類。#
唔,對我來講,最近發生的一件比較重要的事兒就是,我利用一種比較特殊的方法來將類和結構體的成員結合在一起。這是我之前在利用 Objective-C 進行開發的時候養成的習慣。我通常將私有方法放置在最下面,然後公共及初始化方法放在中間。然後將屬性按照公共屬性到私有屬性的順序放置在代碼上層。唔,你可以按照下面的結構在組織你的代碼。
- 公共屬性
- 內聯屬性
- 私有屬性
- 初始化容器
- 公共方法
- 內聯方法
- 私有方法
你也可以按照靜態 / 類屬性 / 固定值的方式進行排序。可能不同的人會在此基礎上補充一些不同的東西。不過對於我來講,我無時不刻都在按照上面的方法進行編程。
好了,本期節目就到此結束。如果你有什麼好的想法,或者什麼想說的話,歡迎通過屏幕下方的聯繫方式聯繫我。當然歡迎通過這樣的方式丟硬幣丟香蕉打賞並訂閱我的文章(大霧)。
下期預告:將繼續講訴 Swift 裡的點點滴滴,不要走開,下期更精彩 。