Kim Derek Chihoon
Kim Derek Chihoon

Reputation: 97

SwiftUI changing text title of navigationBar Button at the current view to "Back" instead of inheriting the text from previous view title

I have a swiftUI view with navigation links that when i click will navigate to another view . The issue is the second view navigationBa button title still has the title of the previous view instead of a logical back title . How i can have the title as Back with changing the title as "Back" in the first view .

First view navigationBar code: The second view just shows the news website in a WebView.

.navigationBarTitle("Breaking News")

The way i tried is changing the title to this:

.navigationBarTitle("Back")

This will work but the title of the first view changes to "Back" Instead of "Breaking News" Is there any way i can fix this

Upvotes: 3

Views: 874

Answers (2)

Vadim Ahmerov
Vadim Ahmerov

Reputation: 777

The accepted answer looks glitchy, it removes a lot of standard behaviour and animations, including long press gesture.

Consider using custom backBarButtonTitle modifier:

struct FirstView: View {
    var body: some View {
        Text("First view")
            .backBarButtonTitle("Back")
    }
}

It sets the backButtonTitle property to the topmost UINavigationItem in stack. Be sure to use this modifier on the view, whose title you want to change, see documentation.

Here is the implementation of the backBarButtonTitle:

import SwiftUI
import UIKit

extension View {
    func backBarButtonTitle(_ title: String) -> some View {
        modifier(BackButtonModifier(title: title))
    }
}

// MARK: - BackButtonModifier

struct BackButtonModifier: ViewModifier {
    let title: String

    func body(content: Content) -> some View {
        content.background(BackButtonTitleView(title: title))
    }
}

// MARK: - BackButtonTitleView

private struct BackButtonTitleView: UIViewRepresentable {
    let title: String

    func makeUIView(context _: Context) -> BackButtonTitleUIView {
        BackButtonTitleUIView(title: title)
    }

    func updateUIView(_: BackButtonTitleUIView, context _: Context) {}
}

// MARK: - BackButtonTitleUIView

private final class BackButtonTitleUIView: UIView {
    // MARK: Lifecycle

    init(title: String) {
        self.title = title
        super.init(frame: .zero)
    }

    required init?(coder _: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: Internal

    override func layoutSubviews() {
        super.layoutSubviews()
        if didConfigureTitle {
            return
        }
        let topNavigationItem = searchNavigationController(currentResponder: self)?
            .topViewController?
            .navigationItem
        if let topNavigationItem {
            topNavigationItem.backButtonTitle = title
            didConfigureTitle = true
        }
    }

    // MARK: Private

    private let title: String
    private var didConfigureTitle = false

    private func searchNavigationController(currentResponder: UIResponder) -> UINavigationController? {
        if let navigationController = currentResponder as? UINavigationController {
            return navigationController
        } else if let nextResponder = currentResponder.next {
            return searchNavigationController(currentResponder: nextResponder)
        } else {
            return nil
        }
    }
}

Upvotes: 0

Harshil Patel
Harshil Patel

Reputation: 1472

An alternative approach is to hide the back button and create your own back button like this:

struct ContentView: View {
    var body: some View {
        NavigationView {
                NavigationLink(destination : SomeView()) {
                    Text("Open")
            }
            .navigationBarTitle("Breaking News")
        }
    }
}

// Use navigationBarItems for creating your own bar item.

struct SomeView : View {
    @Environment(\.presentationMode) var mode
    var body : some View {
        Text("Hello, World!")
            .navigationBarBackButtonHidden(true)
            .navigationBarItems(leading:
            Button(action : {
                self.mode.wrappedValue.dismiss()
            }){
            Text("\(Image(systemName: "chevron.left"))Back")
        })
    }
}

Upvotes: 2

Related Questions