我试图了解_ConditionalContent
的内部工作,但我无法实现它的resultBuilder。_ConditionalContent
的一些resultbuilder是这样定义的:
static func buildEither<T: View, F: View>(first: T) -> _ConditionalContent<T, F>
这对我来说没有意义,因为F
是如何确定的?它不能类型擦除到AnyView
,因为我已经看到两个类型参数是具体的SwiftUI视图,例如。_ConditionalContent<Text, Button>
。只有在与其他buildEither(second:)
函数结合时才有意义,这是确定_ConditionalContent
的最终类型。
我无法得到这个工作的粗略版本,所以如果有人可以向我解释如何使用结果构建器实现这个请告诉我:
struct ConditionalConent<T: View, F: View> {
let trueContent: T
let falseContent: F
}
@resultBuilder
struct ConditionalContentBuilder {
static func buildBlock<V: View>(_ content: V) -> V {
return content
}
static func buildEither<T: View, F: View>(first: T) -> ConditionalContent<T, F> {
// ... how is ConditionalContent created?
}
static func buildEither<T: View, F: View>(second: F) -> ConditionalContent<T, F> {
// ... how is ConditionalContent created?
}
}
结果生成器由SE-0289正式定义。Selection statements一节描述了如何转换if/else
语句。对于你的问题,答案是这句话:
注意,所有对
vMerged
的赋值将一起进行类型检查,这应该允许在注入的结果类型中的任何自由泛型参数是统一的。
通常,在Swift中,每条语句都独立于其他语句进行类型检查,因此if/else
的两个分支中的语句不会影响彼此的类型检查。但是在结果生成器中的if/else
语句中,当两个分支都将结果赋值给同一个(合成的)变量时,Swift同时使用两个分支来推断该变量的类型。
这类似于?:
操作符的两个分支必须具有相同的类型。例如,使用ConditionalContent
的定义,我们可以这样写:
import SwiftUI
struct ConditionalContent<T: View, F: View> {
var condition: Condition
enum Condition {
case isTrue(T)
case isFalse(F)
}
}
let vMerged: ConditionalContent = 1 > 2
? .init(condition: .isTrue(Text("really big one")))
: .init(condition: .isFalse(Text("normal sized one").opacity(0.5)))
print(type(of: vMerged))
// output: ConditionalContent<Text, ModifiedContent<Text, _OpacityEffect>>
Swift可以通过查看?:
操作符的两个分支来推断T
和F
的类型。结果构建器使用if/else
语句的两个分支执行类似的推断。