iosswiftswiftuinavigation

How to navigate in SwiftUI while also executing logic and creating a new Object?


I have a EditTapasView which is there to edit any Tapas created by the user. To create one, they can press a "New Tapas" button, sending them to exactly this EditTapasView with a newly created Tapas.

Until now it all worked with using a sheet.

Button(action: {
    newTapas = addTapas()
    /// Delay the toggle of the Sheet by .1 second.
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
         shouldPresentSheet.toggle()
    }
}, label: {
    Text("New Tapas")
        .font(.system(size: 17))
        .padding(.trailing)
        .padding([.top, .bottom], 10)
})
   .sheet(isPresented: $shouldPresentSheet) {
       print("Sheet dismissed!")
    } content: {
       EditTapasView(tapas: newTapas)
    }

But now I have added a new NavigationLink inside of the EditTapasView to make some edits, and this part is not working in a sheet.

When I just use a NavigationLink and giving it the addTapas() function, it constantly creates new Tapas without any click.

NavigationLink(destination: EditTapasView(tapas: addTapas())) {
    Text("New Tapas")
        .font(.system(size: 17))
        .padding(.trailing)
        .padding([.top, .bottom], 10)
}

Then I researched how to navigate progamatically, but I couldn't make it work.

NavigationStack (path: $path) {
    Button(action: {
        newTapas = addTapas()
        path = EditTapasView(tapas: newTapas)
    }, label: {
        Text("New Tapas")
            .font(.system(size: 17))
            .padding(.trailing)
            .padding([.top, .bottom], 10)
    })
}

So is there any way to solve my problem? Either to simply use NavigationLink (or similar) in the Action part of a button? Or to have some logic execute once a NavigationLink is pressed?


Solution

  • There's probably a few different ways a simple way would be to use navigationDestination if it's not too buggy. The NavigationStacks and NavigationSplitViews aren't really ready for production yet.

    @State private var newTapa: Tapa?
    
    var body: some View {
            NavigationStack {
                Button("Add Tapas") {
                    newTapa = Tapa()
                }
                .navigationDestination(item: newTapa) { tapa in
                    TapaEditView(tapa: tapa)
                }
            }
    }
    

    //UPDATE:

    The following code compiles just fine. In the code above I forgot to make newTapa a binding. Other than that you may have a compile issue elsewhere.

    import SwiftUI
    
    
    struct Tapa: Hashable {
        var name = "Tapa Name"
    }
    
    struct TapaEditView: View {
        let tapa: Tapa
    
        var body: some View {
            Text(tapa.name)
        }
    }
    
    struct SomeView: View {
        @State private var newTapa: Tapa?
    
        var body: some View {
            NavigationStack {
                Button("Add Tapas") {
                    newTapa = Tapa()
                }
                .navigationDestination(item: $newTapa) { tapa in
                    TapaEditView(tapa: tapa)
                }
            }
        }
    }