0

I am using MVVM+C pattern to build my app. Currently I am facing a problem with changing the native back button title and image of navigation bar to the custom image without the title. I've tried a lots of solutions what I was able to find, but nothing set the different title or even an image. I've ended up with this code in AppDelegate.swift:

let navigationController: UINavigationController = .init()
    
    if #available(iOS 13.0, *) {
        let appearence = UINavigationBarAppearance()
        appearence.configureWithOpaqueBackground()
        appearence.backgroundColor = .backgroundColor
        appearence.shadowColor = nil
        appearence.shadowImage = nil
        
        navigationController.navigationBar.standardAppearance = appearence
        navigationController.navigationBar.scrollEdgeAppearance = navigationController.navigationBar.standardAppearance
    } else {
        navigationController.navigationBar.isTranslucent = false
        navigationController.navigationBar.barTintColor = .backgroundColor
        navigationController.navigationBar.shadowImage = nil
        navigationController.navigationBar.shadowColor = nil
    }
    // This code is not working at all, always get "Back" as a default with default image =====

    let backButtonBackgroundImage = UIImage(named: "backButton")
    navigationController.navigationBar.backIndicatorImage = backButtonBackgroundImage
    navigationController.navigationBar.backIndicatorTransitionMaskImage = backButtonBackgroundImage
    
    let backBarButtton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
    navigationController.navigationItem.backBarButtonItem = backBarButtton
    
    // =========

    navigationController.navigationBar.tintColor = .primary
    
    window?.rootViewController = navigationController
    window?.makeKeyAndVisible()

Also, I've followed the official documentation but without any success. As default I've set the navigation bar as hidden (because is not needed for multiple times) and I am showing it in ViewWillAppear and hiding in ViewWillDisappear methods.

Is there someone who has an idea of what's going on? Thanks!

The result of this code: Back button

Expected result: Expected back button

This is what I get with the new code: enter image description here

SOLUTION: After using code from Scott I was able to change the image and look of the navigation bar but I lost the ability to swipe back. After adding this code to the UINavigationBar extension I was able to get it back:

extension UINavigationController: UIGestureRecognizerDelegate {
@objc func goBack(sender: Any?) {
    self.popViewController(animated: true)
}

override open func viewDidLoad() {
    super.viewDidLoad()
    interactivePopGestureRecognizer?.delegate = self
}

public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return viewControllers.count > 1
}
}

1 Answer 1

1

Below is some Playground code that shows a UINavigationController with a custom back button that is an image.

Note that what it does is hides the system provided back button, then substitutes another button that still performs the "back" action but on a custom UINavigationController.

There may be a more efficient way to duplicate the functionality of "back" that doesn't involve a custom class and a custom target-action setup, but I couldn't find one quickly so finding that solution can be left as an exercise for the reader.

import UIKit
import SwiftUI
import PlaygroundSupport

NSSetUncaughtExceptionHandler { error in
    debugPrint(error)
}

class MyNavController : UINavigationController {
    @objc func goBack(sender: Any?) {
        self.popViewController(animated: true)
    }
}

let navDestination1 = UIViewController()
navDestination1.navigationItem.title = "Destination 1"

let navigationController = MyNavController(rootViewController: navDestination1)

if #available(iOS 13.0, *) {
    let appearence = UINavigationBarAppearance()
    appearence.configureWithOpaqueBackground()
    appearence.backgroundColor = .purple
    appearence.shadowColor = nil
    appearence.shadowImage = nil

    navigationController.navigationBar.standardAppearance = appearence
    navigationController.navigationBar.scrollEdgeAppearance = navigationController.navigationBar.standardAppearance
} else {
    navigationController.navigationBar.isTranslucent = false
    navigationController.navigationBar.barTintColor =  .purple
    navigationController.navigationBar.shadowImage = nil
}

let navDestination2 = UITableViewController()
navDestination2.navigationItem.title = "Destination 2"
navDestination2.navigationItem.hidesBackButton = true
navDestination2.navigationItem.leftBarButtonItem = UIBarButtonItem(
    image: UIImage(systemName: "multiply.circle.fill"),
    style: UIBarButtonItem.Style.done,
    target: navigationController,
    action: #selector(MyNavController.goBack))


navigationController.pushViewController(navDestination2, animated: true)

navigationController.view.bounds = CGRect(x: 0,y: 0,width: 320,height: 480)

PlaygroundSupport.PlaygroundPage.current.liveView = navigationController
Sign up to request clarification or add additional context in comments.

11 Comments

Hi Scott, for me in my project all the things remains the same. No change of the icon or title when I've used your code directly in ViewController or also in AppDelegate... I am still able to change only the tint color.
Does the sample I posted, run in a playground, show a custom back button on your setup?
Yeah, I'm able to run it in playground and all is set as desired... but when I put the same code on the same place in my project nothing happens. I am only able to change the colors...
Check the result from the project, it's different from playground
Realize that I didn't have your image and so my code is using one of the system images (the round button with an X in it) instead of whatever image you wanted to use.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.