Swift: 語法秘笈

wwlw5827 8年前發布 | 8K 次閱讀 Swift Apple Swift開發

作者:Andyy Hope, 原文鏈接 ,原文日期:2016/07/20

譯者: 冬瓜 ;校對: Darren ;定稿:千葉知風

↑ ↑ ↓ ↓ ← → ← → B A

無論 Swift 是你的第一門開發語言,還是從 Objective-C 轉來,Swift 這門強大的語言都值得我們去學習和使用,但是 Swift 語法的不斷迭代更新可能會令你畏懼。本文將會列舉一些常見的語法,來幫助你提高 Swift 語言能力,精煉代碼。

閉包(Closure)

() -> Void

有些文章中也會稱作 匿名函數 (unnamed functions),類似于 C 或 Objective-C 中的 block ;閉包是一個很輕量但是功能十分強大的函數,常用于類間的值傳遞,閉包通常作為函數的參數來使用,當然也可以作為變量。

如果你有過 iOS 開發經驗,你在使用 UIView animation 的 API 時肯定會用到閉包:

class func animateWithDuration(_ duration: NSTimeInterval, animations: () -> Void)

animation 參數:傳入動畫相關代碼,例如:

UIView.animateWithDuration(10.0, animations: {
    button.alpha = 0
})

animationWithDuration 這個函數利用了閉包,最終我們看到的效果是 button 逐漸消失,直到 alpha 屬性為 0 (不可見狀態)。

尾部閉包(Trailing closures)

UIView.animateWithDuration(10.0) { 
    button.alpha = 0
}

Swift 的這個特點可以省去很多無用代碼。我們再看上面的代碼,仔細的同學已經發現在相同的 API 我們上面的寫法節省了很多代碼。

因為在 animateWithDuration 方法中最后一個參數是閉包,顧名思義,稱之為 尾部閉包 。尾部閉包允許我們省略參數名,并且能放置在參數表括號以外,進一步簡潔代碼。以下兩個代碼實現功能相同,但是后者使用了尾部閉包:

func say(message: String, completion: () -> Void) {
    print(message)
    completion()
}
...
say("Hello", completion: {
    // prints: "Hello" 
    // Do some other stuff
})
say("Hello") {
    // prints: "Hello"
    // Do some other stuff
}

類型別名(Type Alias)

typealias

當我們大量的使用某一種類型來定義時,類型別名是一種方便的手段。比如說我們有一個函數,它的參數是閉包:

func dance(do: (Int, String, Double) -> (Int, String, Double)) { }

這看上去并不復雜,但是如果我們想在多個函數間相互傳遞這個閉包呢?我們不得不記住他的參數名,以確保它在函數中可傳遞。如果參數名不相同,就無法編譯成功,錯誤日志會提示在這個傳遞過程中保證參數名相同。

func dance(do: (Int, String, Double) -> (Int, String, Double)) { }
func sing(do: (Int, String, Double) -> (Int, String, Double)) { }
func act(do: (Int, String, Double) -> (Int, String, Double)) { }

倘若我們交換參數順序、改變返回值類型,同樣的會出現上述問題。所以,一旦我們更改需求,我們需要更新所有出現這個閉包的地方,這種問題的處理方法將會十分繁瑣。所以,我們引入 類型別名 來解決這個問題。

typealias TripleThreat = (Int, String, Double) -> (Int, String, Double)
...
func dance(dance: TripleThreat) { }
func act(act: TripleThreat) { }
func sing(sing: TripleThreat) { }

現在我們重寫之前的所有方法。如果再想更改參數閉包的話,我們所要做的僅僅是修改 typealias 即可。

類型別名代表性的用法(Famous Type Aliases)

typealias Void = ()
typealias NSTimeInterval = Double

參數名縮寫(Shorthand argument names)

$0, $1, $2...

如果一個閉包中有一個或多個參數,Swift 允許我們通過參數名來訪問參數:

func say(message: String, completion: (goodbye: String) -> Void) {
    print(message)
    completion(goodbye: "Goodbye")
}
...
say("Hi") { (goodbye: String) -> Void in
    print(goodbye)
}
// prints: "Hi"
// prints: "Goodbye"

這個例子中,我們的尾部閉包中有一個名為 goodbye 的 String 型參數,Xcode 會將這個參數放到一個元祖中,然后緊跟著一個類型代表返回值,最后再加上 in 關鍵字來代表參數的結束。下一行則是我們閉包的具體實現。當我們的閉包短小,具有高可讀性時,我們可以追求更加簡潔的寫法。我們現在開始減少代碼,以達到極小:

(goodbye: String) -> Void in

很多代碼都不是必要的,因為我們可以使用 參數名縮寫

say("Hi") { print($0) }
// prints: "Hi"
// prints: "Goodbye"

正如所見,可以省略 goodbye 的參數名,以及 Void 返回值。并且 in 關鍵字也可省略,因為我們沒有使用到參數名稱。由于簡單,每個參數都會依照在閉包中的聲明的順序。甚至,我們可以將閉包做縮行處理。

如果閉包中有多個參數,參數名縮寫將會依照順序排列,例如:

(goodbye: String, name: String, age: Int) -> Void in
// $0: goodbye
// $1: name
// $2: age

Return Self

-> Self

Swift 2.0 發布的時候,帶來了一系列的新特性例如 map 、 flatMap 等等。更有趣的是,在這些方法中,我們同樣的可以使用 $ 符號來通過序號對其操作:

[1, 2, 3, nil, 5]
    .flatMap { $0 }     // remove nils
    .filter { $0 < 3 }  // filter numbers that are greater than 2
    .map { $0 * 100 }   // multiply each value by 100
// [100, 200]

很酷吧?這種寫法比較優雅、可讀,易于理解。我們應該在更多的地方使用它。

另外,我們可以通過閉包創建一個 String 的擴展,我們對 String 上執行一堆操作,并返回自己而不是使函數返回無效:

// extension UIView
func withBackgroundColor(color: UIColor) -> Self {
    backgroundColor = color
    return self
}
func withCornerRadius(radius: CGFloat) -> Self {
    layer.cornerRadius = 3
    return self
}
...
let view = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
          .withBackgroundColor(.blackColor())
          .withCornerRadius(3)

總結

無論你是在寫新的功能還是在讀舊的代碼,你會發現這種精煉代碼的方式在任何地方都適用,并且你已經掌握了精煉方法。由于 Xcode 的自動補全現在還不完善,所以你應該不斷地去質疑自己的代碼,不要過度的依賴自動補全,而是自主完成代碼。

另外,我在 github 上提供了一個playground文件以方便你來測試以上內容。

譯者注:譯者自己整理了原作者的示例代碼,并加上中文注釋,詳見譯者的 Github倉庫

如果你喜歡這篇文章,并且對你的Coding Style有所幫助,可以在 推ter 聯系并follow我。

我將會在九月與一群swift愛好者參與 try! Swift NYC ,到時候我們不見不散。

本文由 SwiftGG 翻譯組翻譯,已經獲得作者翻譯授權,最新文章請訪問http://swift.gg。

 

來自:http://swift.gg/2016/08/17/developing-tvos-apps-for-apple-tv-with-swift/

 

Save

 本文由用戶 wwlw5827 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!