Swift 5.1开始,Swift多了一个Function Builder的特性。Function Builder作用类似于不定参数,区别仅仅是表现形式不同,它可以用语句块接收参数列表,每行代码返回一个参数。虽然这只是一个简单的改进,却让编写UI代码方便很多。在SwiftUI,可以写出这样的代码
VStack {
Text("1")
Text("2")
Text("3")
Text("4")
Text("5")
}
虽然本质和不定参数差不多,但是却大大方便了编程,使得代码更加形象。VStack的初始化函数如下:
@inlinable public init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content)
可见能实现这个功能的背后是ViewBuilder在起作用。
而ViewBuilder的接口如下:
@_functionBuilder public struct ViewBuilder {
/// Builds an empty view from an block containing no statements, `{ }`.
public static func buildBlock() -> EmptyView
/// Passes a single view written as a child view (e..g, `{ Text("Hello") }`) through
/// unmodified.
public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
}
现在我想让数组也实现类似的功能,可以定义一个ArrayBuilder。代码如下:
@_functionBuilder public struct ArrayBuilder {
public static func buildBlock<T>(_ items: T...) -> [T] {
items
}
}
public extension Array {
init(@ArrayBuilder _ builder: () -> Self) {
self = builder()
}
mutating func append(@ArrayBuilder _ builder: () -> Self) {
self.append(contentsOf: builder())
}
}
使用方法
var array = Array {
1
2
3
4
5
}
array.append {
6
7
8
9
10
}
print(array) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]