And*_*cas 12
它可以通过继承 UIBarButtonItem 来完成。在 UIBarButtonItem 上将菜单设置为 nil 不起作用,但您可以覆盖菜单属性并首先阻止设置它。
class BackBarButtonItem: UIBarButtonItem {
@available(iOS 14.0, *)
override var menu: UIMenu? {
set {
// Don't set the menu here
// super.menu = menu
}
get {
return super.menu
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以按照你喜欢的方式在你的视图控制器中配置后退按钮,但是使用 BackBarButtonItem 而不是 UIBarButtonItem。
let backButton = BackBarButtonItem(title: "BACK", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backButton
Run Code Online (Sandbox Code Playgroud)
这是首选,因为您只在视图控制器的导航项中设置 backBarButtonItem 一次,然后无论它要推送什么视图控制器,推送的控制器都会在导航栏上自动显示后退按钮。如果使用 leftBarButtonItem 而不是 backBarButtonItem,则必须在将被推送的每个视图控制器上设置它。
编辑:
长按出现的后退导航菜单是 UIBarButtonItem 的一个属性。视图控制器的后退按钮可以通过设置 navigationItem.backBarButtonItem 属性来自定义,这样我们就可以控制菜单。我看到的这种方法的唯一问题是丢失了系统按钮具有的“返回”字符串的本地化(翻译)。
如果您希望禁用菜单成为默认行为,您可以在一个地方实现这一点,在符合 UINavigationControllerDelegate 的 UINavigationController 子类中:
class NavigationController: UINavigationController, UINavigationControllerDelegate {
init() {
super.init(rootViewController: ViewController())
delegate = self
}
func navigationController(_ navigationController: UINavigationController,
willShow viewController: UIViewController, animated: Bool) {
let backButton = BackBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
viewController.navigationItem.backBarButtonItem = backButton
}
}
Run Code Online (Sandbox Code Playgroud)
它与Andrei Marincas的子类和集合解决方案的思想基本相同。
但是每次按下视图控制器时设置 backBarButtonItem 都会导致后退按钮上出现烦人的转换。
因此,我将 的默认设置器设置UIBarButtonItem.menu为不执行任何操作的代码块,这对 iOS 转换系统没有任何损害。
只需复制此代码即可:
enum Runtime {
static func swizzle() {
if #available(iOS 14.0, *) {
exchange(
#selector(setter: UIBarButtonItem.menu),
with: #selector(setter: UIBarButtonItem.swizzledMenu),
in: UIBarButtonItem.self
)
}
}
private static func exchange(
_ selector1: Selector,
with selector2: Selector,
in cls: AnyClass
) {
guard
let method = class_getInstanceMethod(
cls,
selector1
),
let swizzled = class_getInstanceMethod(
cls,
selector2
)
else {
return
}
method_exchangeImplementations(method, swizzled)
}
}
@available(iOS 14.0, *)
private extension UIBarButtonItem {
@objc dynamic var swizzledMenu: UIMenu? {
get {
nil
}
set {
}
}
}
Run Code Online (Sandbox Code Playgroud)
粘贴到任何地方。在您的中调用它AppDelegate:
@main
class AppDelegate: UIResponder {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// ......
Runtime.swizzle()
return true
}
}
Run Code Online (Sandbox Code Playgroud)