SwiftUI TupleView 和泛型,如何递归解析某些 View 和 Group 的元组

标签 swift generics swiftui

我有不同类型 View 的元组 some View ,也可以有一些 Group 也是泛型类型。现在我考虑如何解析这样的结构来实现 View 数组。

这是初始化程序和调试器屏幕截图

public init<A: View, B: View>(@ViewBuilder content: () -> TupleView<(A, B)>) {

    let views = content().value

    self.childs = [AnyView(views.0), AnyView(views.1)]
}

enter image description here

更新 1

我已经尝试实现@ViewBuilder 返回两个组的 TupleView 的初始化程序,然后我可以通过实现初始化程序的所有排列来启用 View 构建器中组的不同组合。
public init<A: View, B: View>(@ViewBuilder content: () -> TupleView<(Group<A>, Group<B>)>)  {

        let groups = content().value

        groups.0.content...
        groups.1.content... // here content is internal
}

但这里的问题是第一个 Group< TupleView < ... >
不提供对内容属性的公共(public)访问(它被标记为内部)
所以我无法访问此属性的内容。我什至尝试过 Mirror(reflecting: groups.0) 但它也没有帮助,因为我无法将其子值转换为适当的 TupleView ,因为我不知道?泛型类型。

更新 2

所以现在唯一的解决方法 为我的自定义容器添加 10 个以上的 View ,然后像我一样布局这些 View 以实现我自己的自定义 分组 查看而不是组!
struct Grouping: View {

    let childs : [AnyView]

    var body: some View {
        EmptyView()
    }

    public init<A: View>(@ViewBuilder content: () -> A) {
           // this init will be used for any non-supported number of TupleView

           let view = content()
           self.childs = [AnyView(view)]
       }

    // MARK: TupleView support
    public init<A: View, B: View>(@ViewBuilder content: () -> TupleView<(A, B)>) {

           let views = content().value

           self.childs = [AnyView(views.0), AnyView(views.1)]

    }

    // ... other 10 init permutations returning TupleView of views 
}

而在我的 自定义容器 View 然后我可以实现 初始化 采取这个分组 TupleView。
public init(@ViewBuilder content: () -> TupleView<(Grouping, Grouping)>) {

        let groups = content().value
        self.childs = groups.0.childs + groups.1.childs

    }

它接缝完成了这项工作。我不明白为什么 Apple 不提供对群组内容及其 subview 的公开访问。这样我们制作自定义布局组件的方法非常有限

最佳答案

你可以试试这个:

func recursiveViewToViewList<V0: View>(viewGroup: V0) -> [AnyView] {
    [AnyView(viewGroup)]
}
func recursiveViewToViewList<V0: View, V1: View>(viewGroup: TupleView<(V0,V1)>) -> [AnyView] {
    []
        + recursiveViewToViewList(viewGroup: viewGroup.value.0)
        + recursiveViewToViewList(viewGroup: viewGroup.value.1)
}
func recursiveViewToViewList<V0: View, V1: View, V2: View>(viewGroup: TupleView<(V0,V1,V2)>) -> [AnyView] {
    []
        + recursiveViewToViewList(viewGroup: viewGroup.value.0)
        + recursiveViewToViewList(viewGroup: viewGroup.value.1)
        + recursiveViewToViewList(viewGroup: viewGroup.value.2)
}
func recursiveViewToViewList<V0: View, V1: View, V2: View, V3: View>(viewGroup: TupleView<(V0,V1,V2,V3)>) -> [AnyView] {
    []
        + recursiveViewToViewList(viewGroup: viewGroup.value.0)
        + recursiveViewToViewList(viewGroup: viewGroup.value.1)
        + recursiveViewToViewList(viewGroup: viewGroup.value.2)
        + recursiveViewToViewList(viewGroup: viewGroup.value.3)
}
func recursiveViewToViewList<Data: Collection, ID: Hashable, Content: View>(viewGroup: ForEach<Data, ID, Content>) -> [AnyView] {
    viewGroup.data.flatMap {
        recursiveViewToViewList(viewGroup: viewGroup.content($0))
    }
}
struct Grouping: View {
    let childs: [AnyView]
    public init<A: View>(@ViewBuilder content: () -> A) {
        childs = recursiveViewToViewList(viewGroup: content())
    }
}


编辑:这不起作用。重载解析是在泛型实现之前完成的,因此当您只有 : View 时,仅解析第一个函数(基本情况)对泛型参数的约束。最好的机会可能是在那里进行动态调度(可能使用反射,因为您无法对带有开放参数的泛型进行类型检查),尽管我不知道这是否可行,也不知道如何去做。

关于SwiftUI TupleView 和泛型,如何递归解析某些 View 和 Group 的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59047885/

相关文章:

ios - 当用户单击电子邮件项目而不使用 mfmailcomposer 时,如何将收件人传递到共享表中的电子邮件

c++ - 返回不同类型的模板函数

java - Scala 中的新 Java 类 : takes type paremeters

java - 为什么 Java 不使用现有的类语言规范语法来进行泛型类型规范?

ios - 如何显示带有预览的上下文菜单?

ios - 合并:发布者有时会失去值(value)并完成

swift - 使用 SwiftUI 转到新 View

arrays - 如何在 swift 中将一组 int 和字符串分配给一个字符串变量?

Swift 2.1 - 在第一次运行时只预填充一些数据(核心数据)

ios - 仅当所有文本字段都已填写时才在 Swift 中启用按钮