根据swift语言指南,我需要在定义结果构建器时实现buildBlock方法。指南还说:
"静态函数buildBlock(_ components: Component…)>组件
将部分结果数组合并为单个部分结果。结果构建器必须实现此方法。">
显然,形参类型和返回类型应该相同。但是,如果我使用不同的类型,似乎也没有问题。我在下面写了一些简单的代码:
@resultBuilder
struct DoubleBuilder {
static func buildBlock(_ components: Int) -> Double {
3
}
}
在Xcode中编译成功。类型可以不同吗?这似乎与官方指南不一致。
编辑:
SwiftUI中ViewBuilder中buildBlock方法的参数类型也与返回类型不同。例如:
static function buildBlock<C0,>(C0, C1) ->TupleView<(C0, C1)在
当他们说
static func buildBlock(_ components: Component...) -> Component
它们不严格地意味着存在一种类型Component
,buildBlock
必须接收并返回。它们只是表示buildBlock
应该接受一些参数,这些参数的类型是"部分结果"的类型,并返回一个"部分结果"的类型。将它们都称为Component
可能会有点混乱。
我认为Swift进化方案解释得更好一点(强调我的):
这里的输入是微妙的,就像它经常出现在类似宏的特性中一样。在下面的描述中,
Expression
代表any表达式语句可以接受的类型(即原始的部分结果),Component
表示any类型可以被部分或组合结果接受,FinalResult
表示any转换后的函数最终返回的可接受的类型。
因此Component
,Expression
和FinalResult
等不必固定为单一类型。您甚至可以重载buildXXX
方法,正如稍后在演进建议中所演示的那样。
buildXXX
的调用。这时,如果有输入错误,就会报告。 例如,
@resultBuilder
struct MyBuilder {
static func buildBlock(_ p1: String, _ p2: String) -> Int {
1
}
}
func foo(@MyBuilder _ block: () -> Double) -> Double {
block()
}
foo { // Cannot convert value of type 'Int' to closure result type 'Double'
10 // Cannot convert value of type 'Int' to expected argument type 'String'
20 // Cannot convert value of type 'Int' to expected argument type 'String'
}
第一个错误是因为结果生成器的结果类型是Int
,但是foo
的闭包参数期望返回类型是Double
。最后两个原因是因为结果构建器的转换试图调用MyBuilder.buildBlock(10, 20)
。
如果你看一下转换后的闭包,这一切都是有意义的:
foo {
let v1 = 10
let v2 = 20
return MyBuilder.buildBlock(v1, v2)
}
基本上,只要转换后的代码可以编译,就没有问题。
在这里查看更多关于转换的详细信息。