18

Learning to SwiftUI. Trying to navigate to a new view from navigation bar buttton clicked.
The sample code below:

var body: some View {
    NavigationView {
        List(0...< 5) { item in
            NavigationLink(destination: EventDetails()){
                EventView()
            }
        }
        .navigationBarTitle("Events")
            .navigationBarItems(trailing:
                NavigationLink(destination: CreateEvent()){
                    Text("Create Event")
                }
        )
    }
}
Unikorn
  • 1,140
  • 1
  • 13
  • 27
  • Are you trying to push `CreateEvent` onto the navigation stack or are you trying to present it modally? – graycampbell Jul 14 '19 at 03:15
  • Yes, pushing to the navigation stack. – Unikorn Jul 14 '19 at 03:26
  • 1
    Based on the code you provided, I do have a suggestion. It may be that this is just example code, but in this instance, `CreateEvent` should really be presented modally, not pushed onto the navigation stack. The reason is that if you have a list of events that each push a detail view onto the stack when pressed, creating a new event is really a secondary action unrelated to the navigation stack and should really be handled as a temporary view - like creating a new contact in the contacts app or a new calendar event in the calendar app. – graycampbell Jul 14 '19 at 11:59
  • DynamicNavigationDestinationLink seems to do the trick. When I present the view modally, it only works the first time I click the button. Subsequent click does nothing. – Unikorn Jul 14 '19 at 19:30
  • 1
    That is an issue with modal presentation currently and seems to just be a bug. I’m assuming it will be fixed before full release, but yes, at the moment that is a problem with presenting a view modally. If you managed to solve your problem, I’d suggest answering your own question and then accepting it so that people with a similar question can learn from what you’ve done to solve it. – graycampbell Jul 14 '19 at 19:40

4 Answers4

9

Put the NavigationLink into the label of a button.

.navigationBarItems(
      trailing: Button(action: {}, label: {
         NavigationLink(destination: NewView()) {
              Text("")
         }
      }))
Stritt
  • 527
  • 7
  • 7
7

Three steps got this working for me : first add an @State Bool to track the showing of the new view :

@State var showNewView = false

Add the navigationBarItem, with an action that sets the above property :

 .navigationBarItems(trailing:
        Button(action: {
            self.showNewView = true
        }) {
            Text("Go To Destination")
        }
    )

Finally add a navigation link somewhere in your view code (this relies on also having a NavigationView somewhere in the view stack)

NavigationLink(
            destination: MyDestinationView(),
            isActive: $showNewView
        ) {
            EmptyView()
        }.isDetailLink(false)
Luke Smith
  • 1,218
  • 12
  • 17
3

This works for me:

    .navigationBarItems(trailing: HStack { AddButton(destination: EntityAddView()) ; EditButton() } )

Where:

struct AddButton<Destination : View>: View {

    var destination:  Destination

    var body: some View {
        NavigationLink(destination: self.destination) { Image(systemName: "plus") }
    }
}
Chuck H
  • 7,434
  • 4
  • 31
  • 34
2

It is an iOS13 bug at the moment: https://forums.developer.apple.com/thread/124757

The "sort-of" workaround can be found here: https://stackoverflow.com/a/57837007/4514671

Here is my solution: MasterView -

import SwiftUI

struct MasterView: View {

    @State private var navigationSelectionTag: Int? = 0

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DestinationView(), tag: 1, selection: self.$navigationSelectionTag) {
                    EmptyView()
                }
                Spacer()
            }
            .navigationBarTitle("Master")
            .navigationBarItems(trailing: Button(action: {
                self.navigationSelectionTag = 1
            }, label: {
                Image(systemName: "person.fill")
            }))
        }
    }
}

struct MasterView_Previews: PreviewProvider {
    static var previews: some View {
        MasterView()
    }
}

And the DetailsView -

import SwiftUI

struct DetailsView: View {
    var body: some View {
        Text("Hello, Details!")
    }
}

struct DetailsView_Previews: PreviewProvider {
    static var previews: some View {
        DetailsView()
    }
}
Rebeloper
  • 813
  • 10
  • 22