Custom back button for NavigationView's navigation bar in SwiftUI

TL;DR

Use this to transition to your view:

NavigationLink(destination: SampleDetails()) {}

Add this to the view itself:

@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

Then, in a button action or something, dismiss the view:

presentationMode.wrappedValue.dismiss()

Full code

From a parent, navigate using NavigationLink

 NavigationLink(destination: SampleDetails()) {}

In DetailsView hide navigationBarBackButton and set custom back button to leading navigationBatItem,

struct SampleDetails: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var btnBack : some View { Button(action: {
        self.presentationMode.wrappedValue.dismiss()
        }) {
            HStack {
            Image("ic_back") // set image here
                .aspectRatio(contentMode: .fit)
                .foregroundColor(.white)
                Text("Go back")
            }
        }
    }

    var body: some View {
            List {
                Text("sample code")
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: btnBack)
    }
}

SwiftUI 1.0

It looks like you can now combine the navigationBarBackButtonHidden and .navigationBarItems to get the effect you're trying to achieve.

Code

struct Navigation_CustomBackButton_Detail: View {
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        ZStack {
            Color("Theme3BackgroundColor")
            VStack(spacing: 25) {
                Image(systemName: "globe").font(.largeTitle)
                Text("NavigationView").font(.largeTitle)
                Text("Custom Back Button").foregroundColor(.gray)
                HStack {
                    Image("NavBarBackButtonHidden")
                    Image(systemName: "plus")
                    Image("NavBarItems")
                }
                Text("Hide the system back button and then use the navigation bar items modifier to add your own.")
                    .frame(maxWidth: .infinity)
                    .padding()
                    .background(Color("Theme3ForegroundColor"))
                    .foregroundColor(Color("Theme3BackgroundColor"))
                
                Spacer()
            }
            .font(.title)
            .padding(.top, 50)
        }
        .navigationBarTitle(Text("Detail View"), displayMode: .inline)
        .edgesIgnoringSafeArea(.bottom)
        // Hide the system back button
        .navigationBarBackButtonHidden(true)
        // Add your custom back button here
        .navigationBarItems(leading:
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }) {
                HStack {
                    Image(systemName: "arrow.left.circle")
                    Text("Go Back")
                }
        })
    }
}

Example

Here is what it looks like (excerpt from the "SwiftUI Views" book): SwiftUI Views Book Excerpt


Based on other answers here, this is a simplified answer for Option 2 working for me in XCode 11.0:

struct DetailView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var body: some View {

        Button(action: {
           self.presentationMode.wrappedValue.dismiss()
        }) {
            Image(systemName: "gobackward").padding()
        }
        .navigationBarHidden(true)

    }
}

Note: To get the NavigationBar to be hidden, I also needed to set and then hide the NavigationBar in ContentView.

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView()) {
                    Text("Link").padding()
                }
            } // Main VStack
            .navigationBarTitle("Home")
            .navigationBarHidden(true)

        } //NavigationView
    }
}