好的,我自己偶然发现了这个问题。我创建了一个适用于各种情况的解决方案(因此不仅适用于以表单形式呈现的视图控制器)。解决方案在 Swift 3 中,因此您仍然需要将其转换为 Objective-C,但如果您仔细阅读 cmets,这应该不是问题。
解决方案的关键是在键盘动画完成时更新tableView(或scrollview)插图,并且表单在它的新位置上。
在你的 UIViewController 子类中添加:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: .UIKeyboardWillHide, object: nil)
}
这将添加一个观察者,以防键盘显示/隐藏。我们还需要取消订阅这些通知,否则应用会崩溃:
deinit {
NotificationCenter.default.removeObserver(self)
}
最后,最重要的代码:
func getTableViewInsets(keyboardHeight: CGFloat) -> UIEdgeInsets {
// Calculate the offset of our tableView in the
// coordinate space of of our window
let window = (UIApplication.shared.delegate as! AppDelegate).window!
let tableViewFrame = tableView.superview!.convert(tableView.frame, to: window)
// BottomInset = part of keyboard that is covering the tableView
let bottomInset = keyboardHeight
- ( window.frame.height - tableViewFrame.height - tableViewFrame.origin.y )
// Return the new insets + update this if you have custom insets
return UIEdgeInsetsMake(
tableView.contentInset.top,
tableView.contentInset.left,
bottomInset,
tableView.contentInset.right
)
}
func keyboardWillChangeFrame(_ notification: Notification){
guard let info = (notification as NSNotification).userInfo else {
return
}
guard let animationDuration = info[UIKeyboardAnimationDurationUserInfoKey] as? TimeInterval else {
return
}
// Default: keyboard will hide:
var keyboardHeight: CGFloat = 0
if notification.name == .UIKeyboardWillChangeFrame {
// The keyboard will show
guard let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
keyboardHeight = keyboardFrame.cgRectValue.height
}
let contentInsets = getTableViewInsets(keyboardHeight: keyboardHeight)
UIView.animate(withDuration: animationDuration, animations: {
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
}, completion: {(completed: Bool) -> Void in
// Chances are the position of our view has changed, (form sheet)
// so we need to double check our insets
let contentInsets = self.getTableViewInsets(keyboardHeight: keyboardHeight)
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
})
}