SwiftUI NavigationLink返回后视图位置未重置问题求助
解决SwiftUI中键盘弹出后跳转返回视图未复位的问题
我用VStack搭建了一个包含登录/注册视图的页面,键盘弹出时视图会正常上移,但如果在键盘显示状态下点击NavigationLink跳转,返回后视图会停留在上移后的位置,仿佛键盘还在。尝试添加.ignoringSafeArea(.keyboard)修饰符也没解决问题。
前后对比:

演示效果:
相关代码:
var body: some View { ZStack { Color(.systemGroupedBackground).edgesIgnoringSafeArea(.all) VStack { LogoView() .padding(.vertical, 50) if isSigningUp { SignUpView() } else { SignInView() } Spacer() HStack { Text("Don't have an account ?") Button(action: { isSigningUp.toggle() }) { Text("\(invertedAuthCaseLabel) !").foregroundColor(Color("mainColor")) } } }.padding() .frame(maxWidth: 500) } }
解决方案
这个问题源于SwiftUI的安全区域状态在跳转返回后未正确重置,以下是几种可行的解决方式:
方法1:监听键盘通知+返回时强制收键盘
通过监听键盘状态,在视图每次出现时强制收起键盘,触发布局重置:
@State private var keyboardIsVisible = false init() { // 注册键盘通知 NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { _ in self.keyboardIsVisible = false } NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { _ in self.keyboardIsVisible = true } } var body: some View { ZStack { Color(.systemGroupedBackground).edgesIgnoringSafeArea(.all) VStack { // 原有视图内容 LogoView() .padding(.vertical, 50) if isSigningUp { SignUpView() } else { SignInView() } Spacer() HStack { Text("Don't have an account ?") Button(action: { isSigningUp.toggle() }) { Text("\(invertedAuthCaseLabel) !").foregroundColor(Color("mainColor")) } } }.padding() .frame(maxWidth: 500) .onAppear { // 返回时强制收起所有输入框的键盘 UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) keyboardIsVisible = false } } }
方法2:改用NavigationStack(iOS 16+)
如果项目支持iOS 16及以上版本,用NavigationStack替代旧的NavigationLink,它的视图生命周期管理更严谨,能自动避免这类状态残留问题。
方法3:动态忽略键盘安全区域
不要全局忽略键盘安全区域,而是根据键盘状态动态调整:
VStack { // 原有视图内容 } .padding() .frame(maxWidth: 500) .ignoringSafeArea(.keyboard, when: keyboardIsVisible)
内容的提问来源于stack exchange,提问作者Quentin Verchere
相关产品推荐
相关产品推荐

