You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:15:39