SwiftUI中.ignoresSafeArea偶发未包含键盘预测文本栏问题求助
SwiftUI视图被键盘截断的异常问题
问题代码
struct MyRootSwiftUIView: View { var body: some View { VStack{} .ignoresSafeArea(.container, edges: [.bottom]) } }
场景与异常表现
- 该SwiftUI视图由UIViewControllerA承载,预期唤起键盘时视图紧贴键盘上方显示。
- 异常触发路径:
- 打开App内另一个唤起键盘的UIViewControllerB(该控制器不显示预测文本栏)
- 关闭UIViewControllerB,键盘随之收起
- 打开UIViewControllerA,唤起键盘并展示SwiftUI视图
- 此时MyRootSwiftUIView偶尔会被键盘截断约预测文本栏的高度;直接打开UIViewControllerA则无异常,推测是系统残留了UIViewControllerB的安全区域设置。
- 环境:iPhone,iOS 16.3.1(注:原描述的26.3.1应为笔误)
- 问题难以稳定复现,重启App后恢复正常。
问题定性
这属于iOS 16部分版本中,SwiftUI与UIKit跨视图控制器交互时的安全区域同步已知bug,Apple在后续iOS 17版本中针对这类安全区域状态残留问题做了修复。
可行解决方案
1. 强制UIViewControllerA刷新安全区域
在UIViewControllerA的viewWillAppear中手动触发布局更新,强制同步安全区域状态:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) setNeedsUpdateOfHomeIndicatorAutoHidden() view.setNeedsLayout() view.layoutIfNeeded() }
2. 动态监听键盘高度调整布局
放弃依赖系统安全区域自动计算,直接通过键盘通知获取实际高度,调整视图底部padding:
struct MyRootSwiftUIView: View { @State private var keyboardHeight: CGFloat = 0 var body: some View { VStack{} .padding(.bottom, keyboardHeight) .ignoresSafeArea(.container, edges: .bottom) .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in guard let frame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } keyboardHeight = frame.height } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in keyboardHeight = 0 } } }
3. 重置UIViewControllerB的安全区域状态
在UIViewControllerB关闭时,重置其关联的窗口安全区域状态:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) view.window?.safeAreaInsets = .zero view.window?.setNeedsLayout() view.window?.layoutIfNeeded() }
内容的提问来源于stack exchange,提问作者AntcDev
相关产品推荐
相关产品推荐

