UIAlertView (已棄用,iOS 8+ 用 UIAlertController) 自帶輸入框,二次彈出時輸入框異常上移。經排查是第三方輸入法 (搜狗等) 安全區域避讓邏輯與 AlertView 佈局衝突。
UIKeyboardWillShow 通知,計算安全區域並調整視圖框架UIAlertView 內部佈局較舊,對鍵盤通知響應處理不當,導致二次彈出時座標計算錯誤let alert = UIAlertController(title: "標題", message: "消息", preferredStyle: .alert)
alert.addTextField { textField in
textField.placeholder = "請輸入"
textField.isSecureTextEntry = false
}
alert.addAction(UIAlertAction(title: "取消", style: .cancel))
alert.addAction(UIAlertAction(title: "確定", style: .default) { _ in
let input = alert.textFields?.first?.text ?? ""
print("輸入: \(input)")
})
present(alert, animated: true)
UIAlertController 是現代 API,正確處理鍵盤避讓、安全區域、動畫
// 檢測是否第三方輸入法
func isThirdPartyKeyboard() -> Bool {
let primaryLanguage = UITextInputMode.currentInputMode?.primaryLanguage ?? ""
return !primaryLanguage.hasPrefix("en_") && !primaryLanguage.hasPrefix("zh-Hans") && !primaryLanguage.hasPrefix("zh-Hant")
// 簡略判斷,實際需維護白名單
}
// 彈出前提示
if isThirdPartyKeyboard() {
let tip = UIAlertController(title: "提示", message: "檢測到第三方輸入法可能導致界面異常,建議切換系統輸入法", preferredStyle: .alert)
tip.addAction(UIAlertAction(title: "知道了", style: .default))
present(tip, animated: true)
}
@objc func keyboardWillShow(_ notification: Notification) {
guard let userInfo = notification.userInfo,
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
let alertView = presentedViewController as? UIAlertView else { return }
// 手動調整 AlertView frame 避開鍵盤
var frame = alertView.frame
frame.origin.y = min(frame.origin.y, keyboardFrame.origin.y - frame.height - 20)
alertView.frame = frame
}
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
UIAlertView,全面遷移 UIAlertController已解決:項目遷移至 UIAlertController,問題徹底消失。