简体   繁体   English

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

[英]SwiftUI TupleView and generics, how to parse recursively tuple of some View and Group

I have Tuple with views of different types that are some View , there can also be some Group that is also generic type.我有包含不同类型视图的 Tuple 是some View ,也可以有一些 Group 也是通用类型。 Now I consider how can I parse such structure to achieve array of views.现在我考虑如何解析这样的结构来实现视图数组。

Here are initializer and debugger screenshot这是初始化程序和调试器屏幕截图

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

    let views = content().value

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

在此处输入图片说明

UPDATE 1更新 1

I've tried to implement initializer which @ViewBuilder returns TupleView of two Groups, then I can enable different combinations of Groups in View builder by implementing all permutations of initializers.我已经尝试实现@ViewBuilder 返回两个组的 TupleView 的初始化程序,然后我可以通过实现初始化程序的所有排列来启用视图构建器中组的不同组合。

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
}

But here problem is that groups.0 which is first Group< TupleView < ... > doesn't provide public access to content property (it is marked internal ) So I cannot access content of this property.但这里的问题是第一个 Group< TupleView < ... > 不提供对内容属性的公共访问(它被标记为internal )所以我无法访问这个属性的内容。 I have even tried Mirror(reflecting: groups.0) but it also doesn't help as I cannot cast its children values to appropriate TupleView as I doesn't know ?我什至尝试过 Mirror(reflecting: groups.0) 但它也没有帮助,因为我无法将其子值转换为适当的 TupleView ,因为我不知道? generics type.泛型类型。

UPDATE 2更新 2

So now the only workaround to enable addition of more then 10 views to my custom container and then layouting this views as I would is to implement my own custom Grouping view instead of Group!所以现在唯一的解决方法是向我的自定义容器添加 10 个以上的视图,然后像我一样布局这个视图是实现我自己的自定义分组视图而不是组!

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 
}

And in my custom container view then I can implement inits that take this Grouping TupleView.而在我的自定义容器视图,然后我可以实现利用这个分组TupleView inits。

public init(@ViewBuilder content: () -> TupleView<(Grouping, Grouping)>) {

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

    }

And it seams to do the job.它接缝完成了这项工作。 I do not understand why Apple doesn't provide public access to Group content and its subviews.我不明白为什么 Apple 不提供对群组内容及其子视图的公开访问。 This way we have very limited way to make custom layouting components这样我们制作自定义布局组件的方法非常有限

You can try this:你可以试试这个:

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())
    }
}

EDIT: this doesn't work.编辑:这不起作用。 Overload resolution is done before generic realization, so only the first function (the base case one) is resolved when you only have the : View constraint on generic parameters.重载解析是在泛型实现之前完成的,因此当您只有: View泛型参数约束时,只会解析第一个函数(基本情况)。 The best chance may be to do dynamic dispatch there (likely using reflection since you can't typecheck for a generic with open arguments), though I don't know whether it is possible, neither how to do it.最好的机会可能是在那里进行动态调度(可能使用反射,因为您无法对带有开放参数的泛型进行类型检查),尽管我不知道这是否可行,也不知道如何去做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM