Move content for keyboard

The keyboard would cover my login form if I didn’t move the content upward. There are a number of ways to do this, but in this example I used my preferred method: adjust the view’s origin.

Listen for the keyboard’s notifications:

override func viewWillAppear(_ animated: Bool) {
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}


Remove the keyboard if the user taps in the view:

override func viewDidLoad() {
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    view.addGestureRecognizer(tap)
}

@objc func dismissKeyboard() {
    view.endEditing(true)
}


Adjust the view’s origin.

@objc func keyboardDidShow(notification: NSNotification) {
    var info = notification.userInfo
    let keyBoardSize = info![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
    view.frame.origin.y = -(keyBoardSize.height - (tabBarController?.tabBar.frame.height ?? 0.0))
}

@objc func keyboardDidHide(notification: NSNotification) {
    view.frame.origin.y = 0
}

Another way to do this by adjusting bottom constraints

@IBOutlet weak var scrollView: UIScrollView!

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    registerNotifications()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    unregisterNotifications()
}


func registerForKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}

@objc func keyboardWillShow(_ notification: NSNotification) {
    updateBottomLayoutConstraintWithNotification(notification)
}

@objc func keyboardWillHide(_ notification: NSNotification) {
    updateBottomLayoutConstraintWithNotification(notification)
}

private func updateBottomLayoutConstraintWithNotification(_ notification: NSNotification) {
    guard let info = notification.userInfo else {
        return
    }
    
    if let animationDuration = (info[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let keyboardEndFrame = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
        let rawAnimationCurve = (info[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.intValue
        {
            
            let animationCurve = UIViewAnimationOptions.init(rawValue: UInt(rawAnimationCurve))
            let convertedKeyboardEndFrame = view.convert(keyboardEndFrame, from: view.window)
            
            composeViewBottomConstraint.constant = (view.bounds.maxY - convertedKeyboardEndFrame.minY)
            readViewBottomConstraint.constant = (view.bounds.maxY - convertedKeyboardEndFrame.minY)
            quickComposeViewBottomConstraint.constant = (view.bounds.maxY - convertedKeyboardEndFrame.minY)
            
            UIView.animate(withDuration: animationDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
                self.view.layoutIfNeeded()
            }, completion: nil)
            
    }
}

Download Sample Project on GitHub. MIT License.