如何通过按钮点击修改导航返回按钮颜色并解决更新滞后问题
问题根源
navigationItem.backBarButtonItem本质是父控制器提供的配置模板,而非当前导航栏上实际渲染的返回按钮实例:系统仅在详情页首次被展示、导航栈发生push/pop变动时,才会读取父控制器的backBarButtonItem属性生成实际显示的返回按钮。
你在DetailVC中修改父控制器持有的backBarButtonItem的tintColor时,不会触发导航栏的实时重绘,当前显示的返回按钮还是之前生成的旧实例。只有下一次导航状态变动触发系统重新读取配置时,你的修改才会生效,这就是颜色更新始终滞后一次的核心原因。
另外你当前通过遍历splitViewController子控制器获取父控制器的写法耦合了系统容器的层级结构,在不同iOS版本、横竖屏切换场景下很容易失效。
可行解决方案
- 直接修改当前导航栏tintColor(推荐,无延迟、体验最好)
系统返回按钮默认继承导航栏的tintColor属性,直接修改当前导航栏的该属性可以立刻生效,同时同步更新父控制器的配置保证后续导航行为一致:/* DetailVC内选色触发的方法中 */ let selectedColor = getNewColor() // 实时修改当前导航栏着色,立刻生效 self.navigationController?.navigationBar.tintColor = selectedColor // 同步更新父控制器的配置,避免后续页面跳转时颜色还原 if let parentNav = self.splitViewController?.viewControllers.first as? UINavigationController, let parentVC = parentNav.topViewController as? ParentVC { parentVC.navigationItem.backBarButtonItem?.tintColor = selectedColor } - 主动触发导航栏重绘
如果要保留原有修改父控制器属性的逻辑,可以在修改属性后主动触发返回按钮的重建,强制刷新显示:
该方案会有极轻微的UI闪烁,体验弱于第一种方案。/* DetailVC内选色触发的方法中 */ if let parentNav = self.splitViewController?.viewControllers.first as? UINavigationController, let parentVC = parentNav.topViewController as? ParentVC { parentVC.navigationItem.backBarButtonItem?.tintColor = getNewColor() // 强制刷新返回按钮 self.navigationItem.setHidesBackButton(true, animated: false) self.navigationItem.setHidesBackButton(false, animated: false) } - 自定义返回按钮(长期维护推荐)
放弃系统的backBarButtonItem机制,直接给DetailVC的navigationItem.leftBarButtonItem设置自定义返回按钮,完全自主控制按钮的样式、点击事件和颜色,不依赖父控制器配置,不存在层级耦合问题,颜色修改可以实时生效。
内容的提问来源于stack exchange,提问作者fphelp
相关产品推荐
相关产品推荐

