使用 MVVM+C 更改导航栏的后退按钮

Changing the back button of UINavigaitonBar with MVVM+C

我正在使用 MVVM+C 模式构建我的应用程序。目前,我面临将导航栏的本机后退按钮标题和图像更改为没有标题的自定义图像的问题。我尝试了很多我能找到的解决方案,但没有设置不同的标题甚至图像。我在 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()

此外,我已经按照 official documentation 进行操作,但没有任何成功。默认情况下,我将导航栏设置为隐藏(因为多次不需要),我在 ViewWillAppear 中显示它并隐藏在 ViewWillDisappear 方法中。

有人知道发生了什么事吗?谢谢!

这段代码的结果:

预期结果:

这是我使用新代码得到的结果:

解决方案: 使用 Scott 的代码后,我能够更改导航栏的图像和外观,但无法向后滑动。将此代码添加到 UINavigationBar 扩展后,我能够取回它:

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
}
}

下面是一些 Playground 代码,其中显示了 UINavigationController 和自定义后退按钮,该按钮是一个图像。

请注意,它所做的是隐藏系统提供的后退按钮,然后替换为另一个仍执行“后退”操作但在自定义 UINavigationController 上的按钮。

可能有一种更有效的方法来复制不涉及自定义 class 和自定义目标操作设置的“后退”功能,但我无法快速找到一个所以找到该解决方案可以留作 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