自定义重置根视图控制器Segue无法正常显示导航栏标题与按钮
解决自定义Segue重置根视图控制器后导航栏元素不显示的问题
我来帮你搞定这个导航栏标题和按钮不显示的问题!
问题原因分析
你当前的Segue实现只是把目标视图控制器的view直接添加到了源视图的父视图上,但并没有真正完成根视图控制器的重置,也没有正确处理导航控制器的层级关联。导航栏的标题、按钮等元素是和UINavigationController的栈结构(或控制器自身的navigationItem)绑定的,这种直接添加view的方式会让目标控制器处于“游离”状态,无法和导航栏建立正确的关联,自然就无法渲染这些元素了。
修正后的Segue实现
下面是调整后的代码,既保留你想要的滑入转场动画,又能正确重置根视图控制器,让导航栏元素正常显示:
class ResetRootViewControllerSegue: UIStoryboardSegue { override func perform() { // 获取当前应用的主窗口(适配iOS 13+多场景) guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let keyWindow = scene.windows.first(where: { $0.isKeyWindow }) else { super.perform() return } let sourceVC = source let destinationVC = destination // 将目标视图添加到窗口层级 keyWindow.insertSubview(destinationVC.view, aboveSubview: sourceVC.view) // 设置初始动画位置:从屏幕右侧滑入 destinationVC.view.transform = CGAffineTransform(translationX: keyWindow.bounds.width, y: 0) // 执行转场动画 UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: { destinationVC.view.transform = .identity }) { [weak self] _ in guard let self = self else { return } // 动画结束后,正式将目标控制器设置为窗口的根视图控制器 keyWindow.rootViewController = destinationVC // 移除源控制器的视图,避免内存泄漏 sourceVC.view.removeFromSuperview() } } }
额外注意事项
- 如果你的目标控制器是嵌套在
UINavigationController中的,确保在Storyboard里正确配置了导航控制器的根视图控制器,并且目标控制器的navigationItem(比如title、leftBarButtonItem等属性)已经正确设置。 - 代码中使用
weak self避免动画闭包出现循环引用,防止内存泄漏。 - 若你仍在适配iOS 12及以下版本,可以替换窗口获取逻辑为:
guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { super.perform() return }
内容的提问来源于stack exchange,提问作者Vyacheslav
相关产品推荐
相关产品推荐

