創建 UI 時的閉包使用
在 SwiftUI 里閉包出現的頻率特別高,這里我重新梳理了下閉包的定義。
關於閉包
閉包表達式語法的一般形式如下:
{(parameters) -> return type in
// 代碼
}
閉包表達式寫在花括號({})里,關鍵字in用來分隔閉包的參數、返回值與閉包體內的語句
// 傳遞閉包個 sort 方法
arr.sort(by: { (a: Int, b: Int) -> Bool in
return a > b
})
// 閉包可以利用 Swift 的類型推斷能力,可以省略返回類型,以及參數的類型
arr.sort(by: { a, b in
return a > b
})
// 這里移除了關鍵字return。不是所有的閉包語句都可以移除 return 關鍵字
// 這里可以是 因為只有一個表達式 (i < j)。如果存在更多表達式,那么顯式的 return 就是必需的。
arr.sort(by: { a, b in a > b })
// Swift 提供了快捷參數名,可以在內聯閉包 表達式中使用
arr.sort(by: { $0 > $1})
// 如果一個閉包是以一個函數的最后一個參數傳遞的,那么它就可以在函數的圓括號以外內聯。
arr.sort { $0 > $1 }
閉包賦值變量
// 普通方式
var str: String = "str"
// 閉包運行賦值
var str2: String = {
return "str2"
}()
// 基於閉包原理簡化
var str3: String = {
"str3"
}()
// 如果不需要傳遞實參,閉包體前的"="號,和末尾的"()"也可以省略
var str4: String {
"str4"
}
SwiftUI 里的閉包
在聲明式的 UI 創建里大量使用閉包,比如
import SwiftUI
struct Text: View {
var body: some View {
Button(action: {
print("Button Click")
}) {
Text("Hello World!")
}
}
}
這里創建 View、Button 都使用了閉包,看了下 Button 的實現,如下
public struct Button<Label> : View where Label : View {
/// Creates an instance for triggering `action`.
///
/// - Parameters:
/// - action: The action to perform when `self` is triggered.
/// - label: A view that describes the effect of calling `action`.
public init(action: @escaping () -> Void, @ViewBuilder label: () -> Label)
/// Declares the content and behavior of this view.
public var body: some View { get }
/// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = some View
}
在 init 方法里設置了 2 個參數,都是函數類型,在使用時可以利用 swift 的 尾部閉包語法
:如果一個閉包是以一個函數的最后一個參數傳遞的,那么它就可以在函數的圓括號以外內聯,所以 Button 可以如此寫
Button(action: {
print("Button Click")
}) {
Text("Hello World!")
}
也可以這樣寫
Button(action: { print("Button Click") }, label: { Text("Hello World!") })