您将如何创建要循环访问的视图数组,为每个视图创建导航 link?

How would you create an array of views to loop through, to create a navigation link to each one of the views?

我有 8 个视图用于在水平滚动组中用户点击图像并转到相应的视图。 我知道我可以手动执行此操作,但使用 ForEach 循环会节省大量代码,我已经对文本执行了类似的操作,如下所示,我尝试对视图数组执行此操作,但是导航的参数要求 link 使得很难引用视图本身 ,因为它会是这样。 [dogs_and_cats 但导航 link 希望它是 dogs_and_cats()]。然而,由于以下错误,这不起作用:类型 'Any' 在导航 link 行中没有成员 'init' 并且无法将类型 'Barcelona_Museum_of_Contemporary_Art.Type' 的值转换为预期的元素类型 'Any.Protocol' 为每个数组元素。如果您处在我的位置,如果可能的话,您将如何创建一个视图对象数组,并为每个导航循环遍历它们 link?


let museumNamesForLink = [Whitney_Museum_of_American_Art, 
The_Andy_Warhol_Museum, 
Museum_of_Modern_Art, Nakamura_Keith_Haring_Collection, 
Tate_Modern, 
The_Broad_Museum, 
Museum_fu_r_Moderne_Kunst, 
Barcelona_Museum_of_Contemporary_Art]

                     
                    ScrollView(.horizontal, showsIndicators: false) {
                        
                        HStack(alignment: .top, spacing: 0) {
                            
                            ForEach(museumNames.indices) { index in
                                
                                VStack {
                                    NavigationLink(destination: museumNamesForLink[index]()) {
                                            Image(museumNames[index])
                                                .resizable()
                                                .aspectRatio(contentMode: .fit)
                                        
                                    }
                                    Text(museumNames[index])
                                         .bold()
                                         .font(.callout)
                                         .foregroundColor(.white)
                                         .multilineTextAlignment(.center)
                                         .padding(.leading)
                                }
                            }
                        }
                    }

我可能会用一个 enum 来表示不同的博物馆类型,然后用一个 @ViewBuilder 函数和一个 switch 语句来处理这个问题,它可以给你一个不同的 View 基于 enum 被喂给它。

struct ContentView: View {
    
    enum MuseumTypes: CaseIterable {
        case whitney, warhol, moma
        
        var name : String {
            switch self {
            case .whitney:
                return "Whitney Museum"
            case .warhol:
                return "Warhol Musuem"
            case .moma:
                return "Museum of Modern Art"
            }
        }
    }
    
    @ViewBuilder func museumViewForType(type: MuseumTypes) -> some View {
        switch type {
        case .whitney:
            WhitneyView()
        case .warhol:
            WarholView()
        case .moma:
            MomaView()
        }
    }
    
    var body: some View {
        NavigationView {
            VStack {
                ForEach(MuseumTypes.allCases, id: \.self) { museum in
                    NavigationLink(destination: museumViewForType(type: museum)) {
                        Text(museum.name)
                    }
                }
            }
        }
    }
}

struct WhitneyView : View {
    var body: some View {
        Text("Whitney")
    }
}

struct WarholView : View {
    var body: some View {
        Text("Warhol")
    }
}

struct MomaView : View {
    var body: some View {
        Text("MOMA")
    }
}

另一种方法是将所有视图存储在数组中,并用 AnyView() 将它们包装起来,以便它们是同类类型(参见 ),但我认为这不是那么干净或者像我上面详述的方法一样清楚)。另外,通过使用 enum 而不是数组,如果您忘记大小写,编译器会发出警告,并保证您不会遗漏任何内容,也不会超出数组索引的范围。