1

iOS 14 引入了可配置的后退按钮模式。例如。您可以在按钮上有“返回”标签文本,但在紧凑的历史菜单中,您仍然可以看到以前控制器的正确标题。

我正在寻找一种简单、愉快的方式来配置默认模式,因此运行时所有 UIViewController 实例都将设置默认模式,例如UINavigationItemBackButtonDisplayModeGeneric

我想知道是否有一种方法可以在不继承 UIViewController 的情况下做到这一点,或者记得始终手动配置 UIViewController 的每个实例(通过viewController.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeGeneric)。

非常感谢任何不需要对数百个 UIViewController 实例进行大量重构的方便方法!

4

2 回答 2

1

没有子类化我认为是不可能的,因为navigationItem需要一个实例才能使用并且不能直接从扩展中修改

class GenericViewController: UIViewController {
override func viewDidLoad() {
    super.viewDidLoad()
    // your code here  
    viewController.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeGeneric
  }
}

并在需要的地方使用它

class viewController: GenericViewController

这是一种非常好的方法,因为您可以控制实现它的方式以及不考虑它可能不在所有场景中存在的方式

于 2020-10-05T16:42:54.617 回答
0

为了解决同样的问题,我使用了 swizzling 技术

import UIKit

private let swizzling: (UIViewController.Type, Selector, Selector) -> Void = { forClass, originalSelector, swizzledSelector in
    if let originalMethod = class_getInstanceMethod(forClass, originalSelector), let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
        let didAddMethod = class_addMethod(forClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(forClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
}

extension UIViewController {
    
    static func swizzle() {
        let originalSelector1 = #selector(viewDidLoad)
        let swizzledSelector1 = #selector(swizzled_viewDidLoad)
        swizzling(UIViewController.self, originalSelector1, swizzledSelector1)
    }
    
    @objc open func swizzled_viewDidLoad() {
        if let _ = navigationController {
            if #available(iOS 14.0, *) {
                navigationItem.backButtonDisplayMode = .generic
            } else {
                // Fallback on earlier versions
                navigationItem.backButtonTitle = "Back"
            }
        }
        swizzled_viewDidLoad()
    }
}

并在application(_:didFinishLaunchingWithOptions:)通话中

UIViewController.swizzle()
于 2020-11-06T10:38:17.667 回答