iOS 18中Swift的pressesBegan方法失效?如何恢复捕获?
iOS 18 中重新捕获 pressesBegan 事件的解决方案
你的代码在 iOS 17 正常但 iOS 18 失效,主要是因为 iOS 18 对 UIView 的事件处理逻辑、第一响应者状态要求更严格,同时无尺寸视图的事件捕获规则有变化。以下是两种可行的修复方案:
方案一:适配原有 UIViewRepresentable 实现
修改代码,确保视图拥有可交互区域并成为第一响应者:
struct ContentView: View { var body: some View { KeyBoardView() .frame(maxWidth: .infinity, maxHeight: .infinity) // 让视图占满整个父容器,获得交互区域 } } struct KeyBoardView: UIViewRepresentable{ func makeUIView(context: Context) -> KeyEventView { KeyEventView() } func updateUIView(_ uiView: KeyEventView, context: Context) {} class KeyEventView: UIView { // 允许视图成为第一响应者 override var canBecomeFirstResponder: Bool { true } init() { super.init(frame: .zero) translatesAutoresizingMaskIntoConstraints = false isUserInteractionEnabled = true // 明确开启用户交互 } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 视图添加到窗口时,主动成为第一响应者 override func didMoveToWindow() { super.didMoveToWindow() becomeFirstResponder() } override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { super.pressesBegan(presses, with: event) // 保留事件传递链 print("test - pressesBegan triggered") } } }
关键修改点:
- 给
KeyBoardView添加.frame(maxWidth: .infinity, maxHeight: .infinity),解决原视图无尺寸无法接收事件的问题 - 重写
canBecomeFirstResponder返回true,并在didMoveToWindow中调用becomeFirstResponder(),确保视图获得第一响应者身份(iOS 18 部分键盘事件需要此状态) - 添加
super.pressesBegan(presses, with: event),保证事件响应链正常传递,避免系统拦截事件
方案二:改用 SwiftUI 原生 API(推荐)
iOS 17+ 提供了 SwiftUI 原生的按键事件处理修饰符 onKeyPress,无需依赖 UIKit 包装,更符合 SwiftUI 开发风格,iOS 18 中可正常工作:
struct ContentView: View { var body: some View { Color.clear .frame(maxWidth: .infinity, maxHeight: .infinity) .onKeyPress(.any) { press in print("test - 按键触发: \(press.key)") // 返回 .handled 表示消费事件,返回 .forward 表示继续传递事件 return .handled } } }
这个方案无需编写 UIViewRepresentable 代码,实现更简洁,同时能捕获所有按键事件。
内容的提问来源于stack exchange,提问作者micah
相关产品推荐
相关产品推荐

