首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用SwiftUI创建动态视图列表

如何使用SwiftUI创建动态视图列表
EN

Stack Overflow用户
提问于 2019-06-18 17:13:57
回答 8查看 25.6K关注 0票数 40

我可以做一个静态列表,比如

代码语言:javascript
复制
List {
   View1()
   View2()
}

但是,如何从数组中创建元素的动态列表呢?我尝试了以下方法,但遇到错误:包含控制流语句的闭包不能与函数构建器'ViewBuilder'一起使用

代码语言:javascript
复制
    let elements: [Any] = [View1.self, View2.self]

    List {
       ForEach(0..<elements.count) { index in
          if let _ = elements[index] as? View1 {
             View1()
          } else {
             View2()
          }
    }
}

有什么办法可以解决这个问题吗?我试图完成的是一个包含动态元素集的列表,这些元素不是静态输入的。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2019-06-20 15:53:10

看起来答案与将视图包装在AnyView中有关

代码语言:javascript
复制
struct ContentView : View {
    var myTypes: [Any] = [View1.self, View2.self]
    var body: some View {
        List {
            ForEach(0..<myTypes.count) { index in
                self.buildView(types: self.myTypes, index: index)
            }
        }
    }
    
    func buildView(types: [Any], index: Int) -> AnyView {
        switch types[index].self {
           case is View1.Type: return AnyView( View1() )
           case is View2.Type: return AnyView( View2() )
           default: return AnyView(EmptyView())
        }
    }
}

这样,我现在就可以从服务器获取视图数据并组合它们。此外,它们仅在需要时实例化。

票数 43
EN

Stack Overflow用户

发布于 2019-06-18 17:28:09

不能在@ViewBuilder块中使用if/let流控制语句。

这些特殊块中的流控制语句被转换为结构。

例如:

代码语言:javascript
复制
if (someBool) {
    View1()
} else {
    View2()
}

转换为ConditionalValue<View1, View2>

并不是所有的流控制语句在这些块中都可用,例如switch,但这可能会在未来发生变化。

有关这方面的更多信息,请参阅function builder evolution proposal

在您的特定示例中,您可以重写代码,如下所示:

代码语言:javascript
复制
struct ContentView : View {

    let elements: [Any] = [View1.self, View2.self]

    var body: some View {
        List {
            ForEach(0..<elements.count) { index in
                if self.elements[index] is View1 {
                    View1()
                } else {
                    View2()
                }
            }
        }
    }
}
票数 7
EN

Stack Overflow用户

发布于 2019-06-20 02:07:41

您可以使用子视图的动态列表,但您需要小心类型和实例化。作为参考,这是一个动态的“汉堡”演示,github/swiftui_hamburger

代码语言:javascript
复制
// Pages View to select current page
/// This could be refactored into the top level
struct Pages: View {
    @Binding var currentPage: Int
    var pageArray: [AnyView]

    var body: AnyView {
        return pageArray[currentPage]
    }
}

// Top Level View
/// Create two sub-views which, critially, need to be cast to AnyView() structs
/// Pages View then dynamically presents the subviews, based on currentPage state
struct ContentView: View {
    @State var currentPage: Int = 0

    let page0 = AnyView(
        NavigationView {
            VStack {
                Text("Page Menu").color(.black)

                List(["1", "2", "3", "4", "5"].identified(by: \.self)) { row in
                    Text(row)
                }.navigationBarTitle(Text("A Page"), displayMode: .large)
            }
        }
    )

    let page1 = AnyView(
        NavigationView {
            VStack {
                Text("Another Page Menu").color(.black)

                List(["A", "B", "C", "D", "E"].identified(by: \.self)) { row in
                    Text(row)
                }.navigationBarTitle(Text("A Second Page"), displayMode: .large)
            }
        }
    )

    var body: some View {
        let pageArray: [AnyView] = [page0, page1]

        return Pages(currentPage: self.$currentPage, pageArray: pageArray)

    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56645647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档