#ios #swift #back-button #ios14 #back-button-control
#iOS #swift #кнопка возврата #ios14 #кнопка возврата-управление
Вопрос:
В iOS 14 введен настраиваемый режим кнопки возврата. Например. у вас может быть текст метки «Назад» на кнопке, но в меню компактной истории вы все равно можете видеть правильное название предыдущих контроллеров.
Я ищу простой и приятный способ настройки режима по умолчанию, чтобы все экземпляры UIViewController во время выполнения имели установленный режим по умолчанию, например UINavigationItemBackButtonDisplayModeGeneric
Интересно, есть ли способ сделать это без подкласса UIViewController или не забывайте всегда настраивать вручную каждый экземпляр UIViewController (через viewController.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeGeneric
).
Любой удобный метод, который не требует обширного рефакторинга сотен экземпляров UIViewController, с благодарностью!
Ответ №1:
Без подклассов, я думаю, это невозможно, поскольку navigationItem
требуется экземпляр для работы и не может быть изменен непосредственно из расширений
class GenericViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// your code here
viewController.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeGeneric
}
}
И используйте это там, где вам нужно
class viewController: GenericViewController
Это действительно хороший подход, поскольку у вас есть контроль над тем, что его реализует, а что нет, учитывая, что его может не быть во всех сценах
Ответ №2:
Чтобы решить ту же проблему, я использовал метод 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()