bryken
bryken

Reputation: 167

SwiftUI programmatic navigation from within list

I have a navigation requirement that looks something like this:

Navigation Each detail screen can navigation to the next and previous detail screen. At the same time, the "back" button should always go back to the main list (not the previous detail screen).

I'm struggling with how to accomplish this in SwiftUI?

Here is what I have so far:

struct ListView: View {
    @State private var currentDetailShown: Int?
    @State private var listItems: [Int] = Array(repeating: 0, count: 10)

    func goToNext() {
        if let idx = self.currentDetailShown {
            self.currentDetailShown = min(self.listItems.count - 1, idx + 1)
        }
    }

    func goToPrev() {
        if let idx = self.currentDetailShown {
            self.currentDetailShown = max(0, idx - 1)
        }
    }

    var body: some View {
        List {
            ForEach(0..<listItems.count) { index in
                NavigationLink(destination: DetailView(goToNext: self.goToNext, goToPrev: self.goToPrev),
                               tag: index,
                               selection: self.$currentDetailShown) {
                    ListItem(score: listItems[index])
                }
                .isDetailLink(false)
                .onTapGesture {
                    self.currentDetailShown = index
                }
            }
        }
    }
}

What happens with this code is that from the first detail view, it'll move to the to the next detail view and then immediately jump back to the list view.

I feel like I'm overthinking this or missing something obvious...

Upvotes: 0

Views: 326

Answers (1)

user10081458
user10081458

Reputation:

Instead of navigating to each detail from your list, you can navigate to a detailView that can show each detail individually by using a published variable in an observable object. Here is an example

struct MainView: View{
    @EnvironmentObject var viewModel: ViewModel

    var body: some View{
        NavigationView{
            VStack{
            ForEach(self.viewModel.details, id:\.self){ detail in
                NavigationLink(destination: DetailView(detail: self.viewModel.details.firstIndex(of: detail)!).environmentObject(ViewModel())){
            Text(detail)
            }
        }
        }
    }
    }
}

class ViewModel: ObservableObject{
    @Published var showingView = 0
    @Published var details = ["detail1", "detail2", "detail3", "detail4", "detail5", "detail6"]
}

struct DetailView: View{
    @EnvironmentObject var viewModel: ViewModel
    @State var detail: Int
    var body: some View{
        VStack{
        IndivisualDetailView(title: viewModel.details[detail])

        Button(action: {
            self.viewModel.showingView -= 1
        }, label: {
            Image(systemName: "chevron.left")
        })
            Button(action: {
                self.viewModel.showingView += 1
                print(self.viewModel.showingView)
            }, label: {
                Image(systemName: "chevron.right")
            })
    }
    }
}
struct IndivisualDetailView: View{
    @State var title: String
    var body: some View{
        Text(title)
    }
}

Upvotes: 1

Related Questions