You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 16无法在不关闭键盘时弹出UIViewController的问题排查

问题解答

关于Xcode Beta版本的问题

Xcode 14 Beta作为预览版本,确实存在UIKit内部窗口结构的临时调整,导致UIRemoteKeyboardWindow无法被检测到;而稳定版Xcode(如13.4.1)适配的iOS 16模拟器/正式版系统中,该窗口结构并未变更。这属于Beta版本的兼容性问题,正式发布的系统与Xcode中大概率会恢复原有逻辑,但依赖私有窗口类名始终存在风险——苹果可能随时调整内部实现,甚至导致App审核被拒,因此更推荐使用稳定的官方方案实现需求。


替代实现方案

方案1:监听键盘通知,手动调整弹窗位置

通过监听键盘弹出/收起事件,获取键盘高度后调整自定义选择器的位置,确保其显示在键盘上方:

  1. 添加键盘通知监听
override func viewDidLoad() {
    super.viewDidLoad()
    // 注册键盘通知
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

// 键盘弹出时调整选择器位置
@objc private func keyboardWillShow(_ notification: Notification) {
    guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
    let keyboardHeight = keyboardFrame.height
    adjustPickerPosition(keyboardHeight: keyboardHeight)
}

// 键盘收起时恢复选择器位置
@objc private func keyboardWillHide(_ notification: Notification) {
    resetPickerPosition()
}
  1. 设置弹窗样式并调整位置
// 弹窗时使用overCurrentContext,避免关闭键盘
self.myViewController.modalPresentationStyle = .overCurrentContext
self.present(self.myViewController, animated: true)

// 调整选择器到键盘上方
private func adjustPickerPosition(keyboardHeight: CGFloat) {
    let screenHeight = UIScreen.main.bounds.height
    let pickerHeight = self.myViewController.view.frame.height
    self.myViewController.view.frame = CGRect(
        x: 0,
        y: screenHeight - keyboardHeight - pickerHeight,
        width: self.myViewController.view.frame.width,
        height: pickerHeight
    )
}

// 恢复选择器到屏幕底部
private func resetPickerPosition() {
    let screenHeight = UIScreen.main.bounds.height
    let pickerHeight = self.myViewController.view.frame.height
    self.myViewController.view.frame = CGRect(
        x: 0,
        y: screenHeight - pickerHeight,
        width: self.myViewController.view.frame.width,
        height: pickerHeight
    )
}

方案2:使用UIPopoverPresentationController(推荐)

如果自定义选择器是下拉样式,可利用系统的UIPopoverPresentationController,将其锚定到输入框,系统会自动适配键盘弹出时的位置:

self.myViewController.modalPresentationStyle = .popover
if let popoverPC = self.myViewController.popoverPresentationController {
    popoverPC.sourceView = yourTextField // 指定输入框为锚点
    popoverPC.sourceRect = yourTextField.bounds
    popoverPC.permittedArrowDirections = .up // 设置箭头方向
}
self.present(self.myViewController, animated: true)

方案3:自定义承载窗口

创建层级高于键盘的独立窗口,将选择器作为窗口的根视图控制器,确保其始终显示在最上层:

// 创建自定义窗口
let pickerWindow = UIWindow(frame: UIScreen.main.bounds)
pickerWindow.windowLevel = UIWindow.Level.alert + 1 // 层级高于默认弹窗与键盘
pickerWindow.rootViewController = self.myViewController
pickerWindow.makeKeyAndVisible()

// 在选择器关闭时销毁窗口(可在myViewController的dismiss方法中添加)
// pickerWindow.isHidden = true

内容的提问来源于stack exchange,提问作者Meroelyth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:24:19