如何不使用UIBarButtonItem.appearance设置导航栏返回按钮并规避IQKeyboardManager问题
问题
我自定义了如下的UINavigationController:
class CustomNavigationController: UINavigationController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. delegate = self setupDefaultAppearance() } private func setupDefaultAppearance() { UINavigationBar.appearance().tintColor = R.color.textBlack() let titleAttributes: [NSAttributedString.Key: Any] = [ .font: R.font.interMedium(size: 18)! ] UINavigationBar.appearance().titleTextAttributes = titleAttributes // Hide the title in bar button items let backButtonAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont(name: "Helvetica-Bold", size: 0.1)!, .foregroundColor: UIColor.clear] UIBarButtonItem.appearance().setTitleTextAttributes(backButtonAttributes, for: .normal) UIBarButtonItem.appearance().setTitleTextAttributes(backButtonAttributes, for: .highlighted) } }
但这段隐藏返回按钮标题的代码导致IQKeyboardManager出现异常:键盘或选择器视图工具栏上的Done按钮消失了。因此我认为不应使用UIBarButtonItem.appearance()静态方法,请问如何在不引发键盘和选择器视图bug的前提下,移除导航控制器返回按钮的标题?
解决方案
方法1:仅针对导航栏返回按钮设置外观
不要全局修改所有UIBarButtonItem,而是通过限定范围或iOS版本专属API,只修改导航栏内的返回按钮:
private func setupDefaultAppearance() { UINavigationBar.appearance().tintColor = R.color.textBlack() let titleAttributes: [NSAttributedString.Key: Any] = [ .font: R.font.interMedium(size: 18)! ] UINavigationBar.appearance().titleTextAttributes = titleAttributes let backButtonAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 0.1), .foregroundColor: UIColor.clear ] // iOS 15及以上用专属的backButtonAppearance if #available(iOS 15.0, *) { let backButtonAppearance = UIBarButtonItemAppearance() backButtonAppearance.normal.titleTextAttributes = backButtonAttributes backButtonAppearance.highlighted.titleTextAttributes = backButtonAttributes let navBarAppearance = UINavigationBarAppearance() navBarAppearance.backButtonAppearance = backButtonAppearance UINavigationBar.appearance().standardAppearance = navBarAppearance UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance } else { // iOS 15以下,限定仅导航栏内的BarButtonItem生效 UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]) .setTitleTextAttributes(backButtonAttributes, for: .normal) UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]) .setTitleTextAttributes(backButtonAttributes, for: .highlighted) } }
这种方式只会影响导航栏的返回按钮,不会波及IQKeyboardManager的工具栏按钮。
方法2:在ViewController基类中统一设置空标题
创建一个基类ViewController,所有业务页面继承它,在基类中设置返回按钮标题为空:
class BaseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() navigationItem.backButtonTitle = "" } }
这种方式完全不会干扰全局的BarButtonItem样式,是最稳妥的方案。
方法3:通过导航控制器代理统一处理
利用UINavigationControllerDelegate,在页面即将显示时修改前一个页面的返回按钮标题:
extension CustomNavigationController: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 给当前页面的上一个页面设置空返回标题 let viewControllers = navigationController.viewControllers if let index = viewControllers.firstIndex(of: viewController), index > 0 { let previousVC = viewControllers[index - 1] previousVC.navigationItem.backButtonTitle = "" } } }
这种方式无需修改每个页面,在导航控制器层面统一处理,同样不会影响全局BarButtonItem。
内容的提问来源于stack exchange,提问作者Bawenang Rukmoko Pardian Putra
相关产品推荐
相关产品推荐

