0

In the old style of NavigationView I was able to assign manually each view in a Navigation Link. However in iOS16 I don't know how to pass a list of view [MovieTitles(),Literature(),TrafficLights(), HistoryChannel()] in Navigation Destination. I think the problem is the struct TitleLinkPage that builds the array

        //struct to build the list Name of language and page
    struct TitleLinkPage: Identifiable, Hashable {
        var id = UUID ()
        let pageView: any View
        let nameItem: String
    }//End struct TitleLangPage

The entire code here:

        import SwiftUI
    
    struct ContentView: View {
        
        let  titleLink: [TitleLinkPage] = [
            .init(pageView: MovieTitles(), nameItem: "See Movies"),
            .init(pageView: Literature(), nameItem: "Visit Literature"),
            .init(pageView: TrafficLights(), nameItem: "Traffic Information"),
            .init(pageView: HistoryChannel(), nameItem: "See History"),
            ]
        
        var body: some View {
            VStack {
                Text("Welcome to our page")
                
                NavigationStack {
                    List (titleLink) { selectedItem in
                        NavigationLink(selectedItem.nameItem, value: selectedItem)
                        
                    }//End List
                    .navigationDestination(for: TitleLinkPage.self) { selectedItem in
                        selectedItem.pageView
                    }
                    
                }
                
            }
            .padding()
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    //struct to build the list Name items and pageView
    
    struct TitleLinkPage: Identifiable, Hashable {
        var id = UUID ()
        let pageView: any View
        let nameItem: String
    }//End struct TitleLangPage

CNunc
  • 3
  • 3

2 Answers2

0

Edited: I think I figured out what problem you're having and it is indeed with your TitleLinkPage struct. I didn't focus on the fact that it was storing anany View I would avoid this and maybe use the enum example instead or some kind of ViewBuilder, but if you really really really want to store the view in the struct -

struct TitleLinkPage: Identifiable, Hashable {
    var id = UUID ()
    let pageView: AnyView
    let nameItem: String

    static func == (lhs: TitleLinkPage, rhs: TitleLinkPage) -> Bool {
        lhs.id == rhs.id
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

extension TitleLinkPage {
    init<ViewType: View>(pageView:ViewType, nameItem:String) {
        self.nameItem = nameItem
        self.pageView = AnyView(pageView)
    }
}

Further Reading on why this isn't the best choice:


What exactly is the problem you're seeing? I was able to get the following to work with only a slight tweak to your code since I don't have your view types.

import SwiftUI

struct InfoRootView: View {
    
    let  titleLink: [TitleLinkPage] = [
        .init(nameItem: "See Movies"),
        .init(nameItem: "Visit Literature"),
        .init(nameItem: "Traffic Information"),
        .init(nameItem: "See History"),
    ]
    
    var body: some View {
        
        NavigationStack {
            //I put inside the stack assuming you didn't want it to persist
            VStack {
                Text("Welcome to our page")
                List (titleLink) { selectedItem in
                    NavigationLink(selectedItem.nameItem, value: selectedItem)
                }
                .navigationDestination(for: TitleLinkPage.self) { selectedItem in
                    selectedItem.pageView
                }
            }
            .padding()
            
        }
        
        
    }
}

struct TitleLinkPage: Identifiable, Hashable {
    var id = UUID ()
    let nameItem: String
}
extension TitleLinkPage {
    var pageView: some View {
        Text("\(nameItem)")
    }
}

For what it's worth, some people also like to use enums if the list of items isn't going to be too long.

enum InformationType:CaseIterable, Hashable {
    case movies
    case literature
    case traffic
    case history
}

extension InformationType {
    @ViewBuilder var pageView: some View {
        Text(self.description)
    }
    
    var description:String {
        switch self {
        case .movies:
            return "Movies"
        case .literature:
            return "Literature"
        case .traffic:
            return "Traffic"
        case .history:
            return "History"
        }
    }
}

struct InfoRootView: View {
    @State var selection:InformationType?
    
    var body: some View {
        
        NavigationStack {
            //I put inside the stack assuming you didn't want it to persist
            VStack {
                Text("Welcome to our page")
                List (InformationType.allCases, id: \.self) { selectedItem in
                    NavigationLink(selectedItem.description, value: selectedItem)
                }
                .navigationDestination(for: InformationType.self) { selectedItem in
                    selectedItem.pageView
                }
            }
            .padding()
            
        }
        
        
    }
}

carlynorama
  • 166
  • 7
0

Thank you carlynorama, I figured out another solution, similar to yours by using switch case

    //struct to build the list Name of View and page
    struct TitleLinkPage: Identifiable, Hashable {
        var id = UUID ()
        let pageView: String
        let nameItem: String
    }//End struct TitleLangPage
    
    //struct to build page view
    struct ChooseView: View {
        let titleView: String
        var body: some View{
            
            switch titleView{
            case "MovieTitles":
                MovieTitles()
            case "Literature":
                Literature()
            case "TrafficLights":
                TrafficLights()
            case "HistoryChannel":
                HistoryChannel()
            default:
                Text("Choose a view")
            }//End switch
            
        }
    } //End struct ChooseView

CNunc
  • 3
  • 3