I have tried most of the examples here on StackOverflow. I also used Apple\'s. The problem I seem to have with them is that they don\'t account for the UITextField being in
I did a mix between the answer of @Victor and some code that I had. I created a handy extension that can be use across many UITextField.
1.- First we need an extension for the UITextField to manage the keyboard notifications
extension UITextField {
func keepTextFieldAboveKeyboard(tableView:UITableView) {
var willShowNotification: NSObjectProtocol?
var willHideNotification: NSObjectProtocol?
willShowNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in
var userInfo = notification.userInfo!
if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
// Get my height size
let myheight = tableView.frame.height
// Get the top Y point where the keyboard will finish on the view
let keyboardEndPoint = myheight - keyboardFrame.height
// Get the the bottom Y point of the textInput and transform it to the currentView coordinates.
if let pointInTable = self.superview?.convert(self.frame.origin, to: tableView) {
let textFieldBottomPoint = pointInTable.y + self.frame.size.height + 20
// Finally check if the keyboard will cover the textInput
if keyboardEndPoint <= textFieldBottomPoint {
tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint
} else {
tableView.contentOffset.y = 0
}
}
}
NotificationCenter.default.removeObserver(willShowNotification!)
}
willHideNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in
tableView.contentOffset.y = 0
NotificationCenter.default.removeObserver(willHideNotification!)
}
}
}
2.- This previous extension should be call inside textFieldShouldBeginEditing so we can have an extension for that as well
extension UITextField : UITextFieldDelegate {
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
guard let tableView = textField.parentView(of: UITableView.self) else { return true };
textField.keepTextFieldAboveKeyboard(tableView:tableView);
return true;
}
}
3.- Finally as you notice in the previous method, we need the TableView where the cell with the UITextField is located. So we can use this extension (Which is also useful for other purposes)
extension UIView {
func parentView(of type: T.Type) -> T? {
guard let view = self.superview else {
return nil
}
return (view as? T) ?? view.parentView(of: T.self)
}
}
4.- Finally in the cell where the UITextField is located, we just write this simple line of code
textField.delegate = textField;
Completely reusable and universal.