UINavigationItem backBarButtonItem转场时标题无法提前更新的解决方案咨询
我完全懂你的困扰——用backBarButtonItem设置返回标题时,转场过程中更新的标题要等转场完成才显示,而自定义leftBarButtonItem又被禁用。下面给你两个可行的方案,能让标题在转场过程中就生效:
方案1:提前初始化backBarButtonItem,直接修改title属性
问题的核心在于:你之前是重新赋值backBarButtonItem,而不是修改已有按钮的title。当导航控制器开始push转场时,已经根据当前backBarButtonItem创建了返回按钮的视图,这时候重新赋值新的item,导航栏不会立即更新,要等转场完成后才会刷新。
解决思路是提前在vc1中创建好backBarButtonItem的实例,之后只修改它的title:
// 在VC1中定义一个懒加载的自定义返回按钮 lazy var customBackButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) override func viewDidLoad() { super.viewDidLoad() // 提前把这个按钮绑定到navigationItem navigationItem.backBarButtonItem = customBackButton }
之后,当你从数据库拿到计数器值时(不管是在vc1的viewWillAppear,还是转场过程中),直接更新这个按钮的title:
// 拿到最新计数器值后,直接修改已有按钮的标题 customBackButton.title = yourCounterTitleFromDatabase
这样修改会立即同步到导航栏的返回按钮上,哪怕转场正在进行中。
方案2:利用UINavigationControllerDelegate的willShow时机
如果必须在转场触发时才获取计数器值,可以借助导航控制器的代理方法,在转场开始前更新backBarButtonItem的title:
首先在vc1中设置代理并实现方法:
override func viewDidLoad() { super.viewDidLoad() navigationController?.delegate = self } extension VC1: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 确认即将跳转的是VC2 guard viewController is VC2 else { return } // 从数据库获取计数器值 let counterTitle = fetchCounterValue() // 如果backBarButtonItem已存在,直接修改title;否则创建新的 if let existingBackButton = navigationItem.backBarButtonItem { existingBackButton.title = counterTitle } else { navigationItem.backBarButtonItem = UIBarButtonItem(title: counterTitle, style: .plain, target: nil, action: nil) } } }
navigationController(_:willShow:animated:)方法会在导航控制器开始转场前调用,此时导航栏还没渲染返回按钮的视图,修改title会直接应用到即将显示的按钮上,转场过程中就能看到更新后的标题。
为什么原来的方法不生效?
你之前在转场过程中重新赋值vc1.navigationItem.backBarButtonItem,此时导航控制器已经为vc2的导航栏生成了返回按钮的快照/视图,新的backBarButtonItem要等到转场完成、导航栏刷新时才会被替换,所以标题延迟显示。
内容的提问来源于stack exchange,提问作者Paul T.

