swift - 閉包、Type alias、簡寫參數名、self

<h6>無論是你學習的第一門語言是 Swift 還是之前學過 Objective-C,在學習 Swift 的過程中,一定會感嘆它真的是一門超贊的語言。但如果你不熟悉它的某些語法,就可能會被某些寫法嚇到。在這里我會介紹一些在寫 Swift 過程中常見語法,希望你們能用 Swift 寫出更簡潔的代碼。

<h1>Closures(閉包)

() -> Void

<h6>Closure 在 C 或 Objective-C 中也被稱為 “unnamed function”(匿名函數) 或者 “block”(代碼塊)。你可以把閉包當成一個值,傳來傳去,當然也可以把它當成函數的參數。

如果你之前有過 iOS 開發(fā)經驗,那么很有可能調用過這個 UIView 的動畫 API:

class func animate(withDuration duration: NSTimeInterval, animations: @escaping () -> Void)

可以在 animations: 參數中傳入執(zhí)行動畫的代碼,

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

這個animationWithDuration: 函數會使用我們閉包中的代碼,悄悄地做一些神奇的事情,把 button 的透明調整到 0(不可見)
<h1>Trailing closures(尾隨閉包)

 UIView.animate(withDuration: 10.0) {
 button.alpha = 0
 }

<h6>Swift 使用這種方式來減少不必要的語法。如果你仔細看上面的代碼就會發(fā)現,這和之前在 closure 中舉的例子使用的是相同的 API,唯一的區(qū)別是它的語法被簡化了。

因為 animate 函數的最后一個參數是閉包,所以它得名尾隨閉包。尾隨閉包可以省略最后一個參數的名字,并且可以完全把它移出函數參數列表圓括號的外面,這就帶來了更優(yōu)雅和準確的代碼。下面的函數都是相同的,不過后面的使用了尾隨閉包語法

func say(_ message: String, completion: @escaping () -> Void) {
    print(message)
    completion()
}

...

say("Hello", completion: {
// prints: "Hello"
// Do some other stuff
})

say("Hello") {
    // prints: "Hello"
    // Do some other stuff
}

<h1>Type Alias(類型別名)

typealias

<h6>Typealias 是一個能讓我們的寫代碼的時候避免一直重復的實用小工具。有這樣一個函數,參數是一個閉包,

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

<h6>起初這還挺直接容易理解的,但如果把這個閉包傳到其它函數中去呢?我們還要記住這個閉包的簽名,而且在每一個它出現的地方都要確保它的簽名是正確的。如果有的地方寫錯了,編譯器就會報錯。

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)) { }

<h6>如果我們修改了這個閉包的簽名,問題就出現了。比如交換了其中參數或者返回值的順序。我們就得把每一個用到的地方都改一下。這個時候 typealias 就會比較有幫助了。

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

<h6>這樣就好多了,用 typealias 替代了很多重復的代碼,而且如果想更改閉包定義的話,直接改 typealias 就可以了。

<h4> 比較「有名的」typealias

typealias Void = ()
typealias NSTimeInterval = Double

<h1>簡寫參數名

$0, $1, $2...

<h6>如果一個閉包有一個或多個參數,Swift 允許我們給它們定義變量名,

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

<h6>在這個例子中,尾隨閉包有一個名為 goodbype 類型是 String 的參數,Xcode 會自動把它放在一個元組里,接著是 -> 、返回值、還有 in,我們的代碼在下一行。但是這個閉包很小,寫這么多代碼是沒有必要的。來分析一下,如何才能寫更少的代碼。

(goodbye: String) -> Void in

<h6>上面的其實都沒有什么存在的必要性,因為可以使用簡化的參數名,

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

<h1>返回 Self

-> Self

<h6>Swift 2.0 發(fā)布的時候,新增了一些方法,比如 map 和 flatMap,更酷的是,可以通過點語法把這些方法串起來,

[1, 2, 3, nil, 5]
    .flatMap { $0 }     // 清除 nil
    .filter { $0 < 3 }  // 選出小于 3 的值
    .map { $0 * 100 }   // 每個值乘 100
// [100, 200]

是不是很酷!這種語法非常優(yōu)雅,很容易閱讀和理解,我們應該盡可能多地使用它們。

如果存在一個 String 的 extension,在此方法里面我們做了一些對于這個 String 本身的操作,這個時候函數不要返回 Void,而返回 Self,

// extension UIView

func with(backgroundColor: UIColor) -> Self {
    backgroundColor = color
    return self
}

func with(cornerRadius: CGFloat) -> Self {
    layer.cornerRadius = 3
    return self
}

...

let view = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
          .with(backgroundColor: .black)
          .with(cornerRadius: 3)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容