0

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...

1 Answer 1

1

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)
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Really appreciate this solution. I was able to get something similiar to what you suggested. This definitely works. However, because this just changes the state behind a single Detail view, there is no "animation" that takes place. Would you have any suggestions on this?
You could use some transitions as seen in developer.apple.com/tutorials/swiftui/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.