iOS17中NavigationStack自定义返回按钮点击后黑屏问题求助
升级到iOS17与Xcode15后,使用NavigationStack的自定义返回按钮调用path.removeLast()时,页面会先变黑再返回至InitView,但侧滑返回功能正常。iOS17之前点击返回按钮会平滑侧滑关闭页面,无此问题。
相关代码
InitView
NavigationStack { // 页面内容 } .navigationDestination(for: String.self) { route in switch route { case "LoginView": LoginView(path: $path) case "RegisterView": RegisterView(path: $path) case "ResetPasswordView": ResetPasswordView(path: $path) default: Text("Unknown") } }
LoginView
struct LoginView: View { @Binding var path: NavigationPath var body: some View { VStack { Button(action: { // 此代码不会触发黑屏 // self.presentationMode.wrappedValue.dismiss() // 此代码会导致LoginView先变黑再返回InitView path.removeLast() }, label: { ZStack { RoundedRectangle(cornerRadius: 7) .stroke(.gray.opacity(0.3), lineWidth: 3) .frame(width: 30, height: 30) Image(systemName: "chevron.left") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 8) .bold() .foregroundColor(.gray) } }) } .navigationBarBackButtonHidden() } }
恢复侧滑返回的扩展代码
extension UINavigationController: UIGestureRecognizerDelegate { override open func viewDidLoad() { super.viewDidLoad() interactivePopGestureRecognizer?.delegate = self } public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return viewControllers.count > 1 } // 让侧滑在ScrollView中也能生效 public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { true } }
解决方案
这个问题是iOS17中NavigationStack的path操作与自定义导航栏隐藏结合时的动画兼容问题,可通过以下方式解决:
方式一:使用环境变量的dismiss方法
在子视图中注入NavigationStack的环境代理,调用官方返回方法保留平滑动画:
struct LoginView: View { @Binding var path: NavigationPath @Environment(\.dismiss) private var dismiss // 新增环境变量 var body: some View { VStack { Button(action: { dismiss() // 使用官方dismiss方法 }, label: { // 按钮UI保持不变 ZStack { RoundedRectangle(cornerRadius: 7) .stroke(.gray.opacity(0.3), lineWidth: 3) .frame(width: 30, height: 30) Image(systemName: "chevron.left") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 8) .bold() .foregroundColor(.gray) } }) } .navigationBarBackButtonHidden() } }
方式二:给path操作添加显式动画
如果必须使用path.removeLast(),将操作包裹在withAnimation中强制启用导航转场动画:
Button(action: { withAnimation(.default) { path.removeLast() } }, label: { // 按钮UI保持不变 })
方式三:调整侧滑扩展逻辑
全局UINavigationController扩展可能干扰iOS17的导航动画,修改扩展仅在必要时启用侧滑:
extension UINavigationController: UIGestureRecognizerDelegate { override open func viewDidLoad() { super.viewDidLoad() if let gesture = interactivePopGestureRecognizer { gesture.delegate = self } } public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { return viewControllers.count > 1 && !isNavigationBarHidden } }
内容的提问来源于stack exchange,提问作者Etienne
相关产品推荐
相关产品推荐

