iOS 17中SwiftUI Push导航动画异常:设置delegate=self引发卡顿
你的代码在iOS 16及更早版本运行正常,但iOS 17中设置delegate = self会导致Push导航动画卡顿,无法平滑完成从右到左的过渡。
问题根源
你通过扩展让UINavigationController自身实现UINavigationControllerDelegate并设置自己为代理,这种写法在iOS 17中会干扰导航控制器的内部动画调度逻辑,引发动画异常。
解决方案
不要让导航控制器的全局扩展同时承担自身代理角色,将代理逻辑拆分到独立类中,避免内部回调冲突:
方案1:拆分手势代理与导航代理
// 仅用扩展处理侧滑返回手势 extension UINavigationController: UIGestureRecognizerDelegate { override open func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self } public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return viewControllers.count > 1 } } // 单独创建导航代理类处理willShow回调 class NavigationCallbackHandler: NSObject, UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 在这里添加你需要的业务代码 } } // 使用导航控制器时设置代理 let rootVC = YourRootViewController() let navController = UINavigationController(rootViewController: rootVC) navController.delegate = NavigationCallbackHandler()
方案2:使用导航控制器子类(更可控)
如果项目中导航控制器有统一配置需求,建议创建子类而非全局扩展:
class CustomNavigationController: UINavigationController { private let navDelegate = NavigationCallbackHandler() override func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self delegate = navDelegate } } extension CustomNavigationController: UIGestureRecognizerDelegate { func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return viewControllers.count > 1 } } class NavigationCallbackHandler: NSObject, UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 你的业务代码 } }
原理说明
iOS 17对UINavigationController的代理回调时机和内部动画流程做了优化调整,当导航控制器自身作为代理时,会在动画执行阶段触发额外的回调冲突,导致动画帧丢失、出现卡顿。将代理逻辑分离到独立对象后,能避免这种内部干扰,让导航动画恢复平滑过渡。
内容的提问来源于stack exchange,提问作者Aaban Tariq Murtaza
相关产品推荐
相关产品推荐

