2022/08/30
Xcode 14
iOS 16
macOS 13
在以往的命令式编程中,通常这样构建视图:
1 | let label = UILabel() |
但 SwiftUI 采用的是声明式语法:
1 | VStack { |
显而易见,SwiftUI 比 UIKit 要简洁地多,我们可以轻松地将不同的视图组合成复杂的界面。这得益于 Result builders(结果构造器),它使 SwiftUI 成为了特定领域语言(DSL)。
结果构造器是 Swift 5.4 正式引入的新特性,它可以将一系列子对象组合成新的对象,这个新对象又可以作为子对象去构造更复杂的对象。它在 SwiftUI 中无处不在,如构建场景的 @SceneBuilder
,构建视图的 @ViewBuilder
,还有 Swift 5.7 新增的正则构造器 RegexBuilder 等。
下面通过一个简单的示例来演示结果构造器的基本使用,假设我们想赋予 UIKit 类似 SwiftUI 的声明式语法,首先声明一个构造器:
1 | @resultBuilder struct VStackBuilder { |
如上所示,要实现一个结果构造器,需要使用 @resultBuilder
修饰,并且必须实现 buildBlock
方法。
然后可以使用 @VStackBuilder
修饰相应的构造块(build block),如下的 VStack 会从 content 闭包构建视图:
1 | final class VStack: UIStackView { |
然后就可以愉快地使用 VStack 了:
1 | class ViewController: UIViewController { |
如果需要在 VStack 中条件渲染视图,只需在相应的 VStackBuilder 中实现相应的静态方法 buildEither
即可:
1 | static func buildBlock(_ component: UIView) -> UIView { |
然后就可以这样写:
1 | VStack { |
关于结果构造器的更多细节和使用参考:SE-0289。
结果构造器使用简单,但效果神奇!它可以快速地实现 DSL,简化工作。
上例只实现了小部分构件 UI 的功能,并不具备数据绑定和更新状态的能力。此处仅为演示结果构造器的基本用法,并无指导意义。如果你的项目支持的最低版本为 iOS 13,可桥接使用 SwiftUI。
Github 有个仓库收集了许多 Result builders 的用法,参考:awesome-result-builders。