swift - 閉包、Type alias、簡(jiǎn)寫參數(shù)名、self

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

<h1>Closures(閉包)

() -> Void

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

如果你之前有過(guò) iOS 開發(fā)經(jīng)驗(yàn),那么很有可能調(diào)用過(guò)這個(gè) UIView 的動(dòng)畫 API:

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

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

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

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

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

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

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

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 是一個(gè)能讓我們的寫代碼的時(shí)候避免一直重復(fù)的實(shí)用小工具。有這樣一個(gè)函數(shù),參數(shù)是一個(gè)閉包,

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

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

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>如果我們修改了這個(gè)閉包的簽名,問(wèn)題就出現(xiàn)了。比如交換了其中參數(shù)或者返回值的順序。我們就得把每一個(gè)用到的地方都改一下。這個(gè)時(shí)候 typealias 就會(huì)比較有幫助了。

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

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

<h4> 比較「有名的」typealias

typealias Void = ()
typealias NSTimeInterval = Double

<h1>簡(jiǎn)寫參數(shù)名

$0, $1, $2...

<h6>如果一個(gè)閉包有一個(gè)或多個(gè)參數(shù),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>在這個(gè)例子中,尾隨閉包有一個(gè)名為 goodbype 類型是 String 的參數(shù),Xcode 會(huì)自動(dòng)把它放在一個(gè)元組里,接著是 -> 、返回值、還有 in,我們的代碼在下一行。但是這個(gè)閉包很小,寫這么多代碼是沒有必要的。來(lái)分析一下,如何才能寫更少的代碼。

(goodbye: String) -> Void in

<h6>上面的其實(shí)都沒有什么存在的必要性,因?yàn)榭梢允褂煤?jiǎn)化的參數(shù)名,

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

可以看到,省略了 goodbye: 參數(shù)名,Void 返回類型的定義,還有跟在后面的 in。每一個(gè)參數(shù)依據(jù)它們?cè)陂]包中定義的順序而命名。因?yàn)檎Z(yǔ)法太簡(jiǎn)略了,甚至能把所有的代碼放到一行。

如果閉包的參數(shù)多于一個(gè),對(duì)于每一個(gè)后面的參數(shù),增加簡(jiǎn)寫參數(shù)的數(shù)字就可以了。

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

<h1>返回 Self

-> Self

<h6>Swift 2.0 發(fā)布的時(shí)候,新增了一些方法,比如 map 和 flatMap,更酷的是,可以通過(guò)點(diǎn)語(yǔ)法把這些方法串起來(lái),

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

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

如果存在一個(gè) String 的 extension,在此方法里面我們做了一些對(duì)于這個(gè) String 本身的操作,這個(gè)時(shí)候函數(shù)不要返回 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)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容