SwiftUI Как изменить страницу из другой ячейки списка?

Я слушал @sonle об использовании NavigationStack. Я думаю, что что-то идет не так. Он осуществляет навигацию, но не так, как я ожидал, до пункта назначения в разделе «Детали путешествия». Это выглядит так.

NavigationLink(destination: {
TravelDetail(TourID: item.id)
}, label: {
TourItemView(tableItem: item)
})

------------ВОПРОС ------------

У меня есть ScrollView, содержимое которого генерируется ForEach, анализируя элементы в struct Array. Я надеюсь, что нажатие на разные ячейки приведет к странице сведений и загрузит информацию о соответствующих объектах. Как я могу этого добиться?

Я обертываю стиль каждой ячейки в кнопку и планирую выполнить действие по изменению страницы через событие нажатия кнопки. В то же время я получаю идентификатор элемента на странице списка и загружаю содержимое на страницу сведений после перехода на страницу. Я пытаюсь использовать NavigationView для прыжков, но меня смущает расположение NavigationLink. Я хочу знать, нормальный ли это метод.

Я думаю, что это основной вопрос, но я в тупике. Как видите, я новичок, поэтому, если у вас есть какие-либо справочные методы, предоставьте их мне. Большое спасибо!

И если есть необходимость предоставить другие части кода, пожалуйста, дайте мне знать.

Страница списка:

import SwiftUI


struct ContentView: View {
    var tableItems: [TableItem]
    
   

        
    init() {
        var items = [TableItem]()
        for index in 0..<tour.count {
            let tourItem = [tour[index]]
            let userItem = [user[index]]
            let tableItem = TableItem(tourItem: tourItem, user: userItem)
            items.append(tableItem)
        }
        self.tableItems = items
        
    }
    
    var body: some View {
        NavigationView {
            VStack {
                            ScrollView(.vertical){
                                VStack(spacing: 8){
                                    ForEach(tableItems, id: \.id) { item in
                                        Button(action: {
                                           
                                        }) {
                                            TourItemView(tableItem: item)
                                        }//ButtonStyle
                                        
                                        
                                        
                                    }//ForEach
                                    
                                }//VStack
                            }//ScrollView
                            
                        }//VStack
                        .padding()

        }//NavigationView
            
        }//view
    
}//ContentView

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


Подробная страница:

import SwiftUI




struct TravelDetail: View {
    
    //let DetailItem: TravelDetailConstant
    
    var ItemID: String
    var result: TravelDetailConstant?
    
    init(TourID: String) {
        self.ItemID = TourID
        
        result = initializersTourItem(id: ItemID)
        
    }
    
    func initializersTourItem(id: String)-> TravelDetailConstant {
        guard let register = ContentView().tableItems.first(where: { $0.id == id }),
                  let initTour = tour.first(where: { $0.id == id }),
                  let initUser = user.first(where: { $0.id == initTour.mainKeeper })
        else {
            return TravelDetailConstant(
                        imagetext: "",
                        title: "",
                        startTime: "",
                        finishTime: "",
                        place: "",
                        peopleNum: "",
                        detailLocaltion: "",
                        meetingPlace: "",
                        tag: nil,
                        detailContent: "",
                        userImage: "",
                        userNikename: "",
                        userGender: "",
                        userBadge: []
                    )
        }
        
        let detail = TravelDetailConstant(imagetext: register.tourImage, title: register.title, startTime: register.startTime, finishTime: initTour.finishTime, place: register.location, peopleNum: register.peopeleNum, detailLocaltion: initTour.detailLocaltion, meetingPlace: initTour.meetingPlace, tag: register.tag, detailContent: initTour.detailContent, userImage: register.userImage, userNikename: register.userName, userGender: initUser.userGender, userBadge: initUser.userBadge)
        
        return detail
        
    }
    
    var body: some View {
        VStack{
            Spacer()
                .frame(height: 20)
            HStack{
                Image((result?.userImage)!)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 75, height: 75)
                    .clipShape(Circle())
                    .background(
                                    Circle()
                                        .padding(-2)
                                        .foregroundColor(Color("DesignLightMutedOrange"))
                                )
                    .padding(.leading, 15)
                VStack{
                    HStack{
                        Text((result?.userNikename)!)
                            .frame(width: 186, height: 28)
                            .padding(.trailing, 12)
                        Image((result?.userGender)!)
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .frame(width: 24, height: 24)
                    }
                    .padding(.bottom, 4)
                    ScrollView(.horizontal) {
                        
                        Button(action: {}) {
                                                Image("")
                                            }
                    }
                    .frame(width: 186, height: 28)
                }
                Button(action: { }) {
                    Image("heart")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: 24, height: 24)
                        .padding(.trailing, 15)
                }
            }
            Spacer().frame(height: 20)
                    HStack{
                        Button(action: {
                            
                        }){
                            Text("Detail")
                        }
                        .frame(width: 150, height: 52, alignment: .leading)
                        .background(Color .red)
                        .padding(.leading, 0)
                        Button(action: {
                            
                        }){
                            Text("Q&A")
                        }
                        .frame(width: 150, height: 52, alignment: .leading)
                        .background(Color .gray)
                        .listRowInsets(EdgeInsets())
                        Spacer()
                    }
            Spacer()
            }
        
    }
}

struct TravelDetail_Previews: PreviewProvider {
    static var previews: some View {
        TravelDetail(TourID: "")
    }
}

57
1

Ответ:

Решено

Поскольку NavigationView устарел, я предлагаю вместо него использовать NavigationStack. Что-то вроде:

struct ContentView: View {
    @State private var path = NavigationPath()
    var body: some View {
        NavigationStack(path: $path) {
            VStack {
                ....
                //Other stuff
                Button(action: {
                    path.append(item)
                }, label: {
                    TourItemView(tableItem: item)          
                })

                //OR
                //NavigationLink(value: item) {
                //    TourItemView(tableItem: item)
                //}
            }
            .navigationDestination(for: TableItem.self) { item in
                TourItemView(tableItem: item)
            }
        }
    }
}

Ваша TableItem модель должна полностью соответствовать Hashable протоколу.

struct TableItem: Hashable {
    ...
}