如何在SwiftUI中创建条件内容?



我试图了解_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可以通过查看?:操作符的两个分支来推断TF的类型。结果构建器使用if/else语句的两个分支执行类似的推断。

相关内容

  • 没有找到相关文章

最新更新