Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: How can I get the selected row in a List before pushing another view

Tags:

ios

swift

swiftui

Another SwiftUI struggle!

I have a view that contains a list. When user taps on a row, I want to first save the selected item in my VM then push another view. The only way I can think of to solve that issue is to first save the selected row and have another button to push the next view. It seems impossible to do this with only one tap.

Anyone have a clue?

Here's the code by the way:

struct AnotherView : View {
    @State var viewModel = AnotherViewModel()

    var body: some View {
        NavigationView {
            VStack {
                    List(viewModel.items.identified(by: \.id)) { item in
                        NavigationLink(destination: DestinationView()) {
                            Text(item)
                        }
                        // Before the new view is open, I want to save the selected item in my VM, which will write to a global store.
                        self.viewModel.selectedItem = item
                    }
                }
        }
    }
}

Thank you!

like image 204
Benjamin Clanet Avatar asked Jul 16 '19 13:07

Benjamin Clanet


2 Answers

Alright, I found a not too shady solution. I used this article https://ryanashcraft.me/swiftui-programmatic-navigation shout out to him! Instead of using a NavigationLink button, I use a regular button, save the selected item when the user tap then use NavigationDestinationLink to push the new view as is self.link.presented?.value = true.

Works like a charm as of beta 3! I'll update my post if something change in the next betas.

Here's how it could look like:

struct AnotherView : View {
    private let link: NavigationDestinationLink<AnotherView2>
    @State var viewModel = AnotherViewModel()

    init() {
        self.link = NavigationDestinationLink(
            AnotherView2(),
            isDetail: true
        )
    }

    var body: some View {
        NavigationView {
            VStack {
                List(viewModel.items.identified(by: \.id)) { item in
                    Button(action: {
                        // Save the object into a global store to be used later on
                        self.viewModel.selectedItem = item
                        // Present new view
                        self.link.presented?.value = true
                    }) {
                        Text(value: item)
                    }
                }
            }
        }
    }
}
like image 176
Benjamin Clanet Avatar answered Sep 28 '22 07:09

Benjamin Clanet


You can add simple TapGesture

                NavigationLink(destination: ContentView() ) {
                    Text("Row")
                        .gesture(TapGesture()
                            .onEnded({ _ in
                                //your action here
                    }))
                }
like image 38
Ivan Titkov Avatar answered Sep 28 '22 07:09

Ivan Titkov