创建 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!") })