I know I'm a bit to late to the party, but since last answer was around 2 years ago I think I can provide more value to this question.
My example works on Swift 5.5+, but should be okay with lower versions as well.
I my scenario I needed some sort of more universal, yet configurable solution, that would allow me to move view with keyboard and control spacings in any UIViewController class that I have in project.
Here are steps, that you need to make in order for it to work:
Step one:
Create outlet for your view bottom constraint and define custom spacings for keyboard and your source view:
@IBOutlet weak var <<yourViewName>>BottomConstraint: NSLayoutConstraint! // Your view's bottom constraint, that should be connected to safe/area or superview
private let <<yourViewName>>BottomSpacing: CGFloat = 56 // Spacing between view and safe area/superview when keyboard is hidden
private let <<yourViewName>>KeyboardSpacing: CGFloat = 22 // Spacing between active keyboard and your view
Step two:
Register observers in our view controller that will track show/hide of keyboard (you can call this method in viewDidLoad or init depending on your needs) Please mind, that you have to remove observers manually in i.e. deinit in older versions of Swift:
private func addKeyboardObservers() {
    // Notifications for when the keyboard show/hides
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.keyboardWillShow),
                                           name: UIResponder.keyboardWillShowNotification,
                                           object: nil)
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.keyboardWillHide),
                                           name: UIResponder.keyboardWillHideNotification,
                                           object: nil)
}
Step three:
Add this code to your UIViewController class. This code will be called as a result of NotificationCenter observers:
@objc private func keyboardWillShow(_ notification: NSNotification) {
    moveViewWithKeyboard(notification: notification,
                         keyboardWillShow: true,
                         viewBottomConstraint: <<yourViewName>>BottomConstraint,
                         activeKeyboardToViewSpacing: <<yourViewName>>KeyboardSpacing,
                         hiddenKeyboardToViewSpacing: <<yourViewName>>BottomSpacing)
}
@objc private func keyboardWillHide(_ notification: NSNotification) {
    moveViewWithKeyboard(notification: notification,
                         keyboardWillShow: false,
                         viewBottomConstraint: <<yourViewName>>BottomConstraint,
                         activeKeyboardToViewSpacing: <<yourViewName>>KeyboardSpacing,
                         hiddenKeyboardToViewSpacing: <<yourViewName>>BottomSpacing)
}
Step Four:
Last part of puzzle, method, that gets keyboard size, calculates spacings and moves view accordingly.
Usually, in my projects I have a file named UIViewController+Keyboard.swift with this code in extension to UIViewController. You can also add other code, that corresponds to keyboard management, like hiding it when user taps around, as in example below:
extension UIViewController {
func hideKeyboardWhenTappedAround() {
    let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
    tap.cancelsTouchesInView = false
    view.addGestureRecognizer(tap)
}
@objc
func dismissKeyboard() {
    view.endEditing(true)
}
func moveViewWithKeyboard(notification: NSNotification,
                          keyboardWillShow: Bool,
                          viewBottomConstraint: NSLayoutConstraint,
                          activeKeyboardToViewSpacing: CGFloat,
                          hiddenKeyboardToViewSpacing: CGFloat) {
    
    guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
    let keyboardHeight = keyboardSize.height
    let keyboardAnimationDuration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
    let keyboardAnimationCurve = UIView.AnimationCurve(rawValue: notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! Int)!
    
    // Modifying spacing constants
    if keyboardWillShow {
        let safeAreaExists = self.view?.window?.safeAreaInsets.bottom != 0
        // Default value in case something goes wrong with bottom spacings
        let bottomConstant: CGFloat = 20
        viewBottomConstraint.constant = keyboardHeight + (safeAreaExists ? 0 : bottomConstant) + activeKeyboardToViewSpacing
    } else {
        viewBottomConstraint.constant = hiddenKeyboardToViewSpacing
    }
    
    // Animating the view the same way the keyboard animates
    let animator = UIViewPropertyAnimator(duration: keyboardAnimationDuration, curve: keyboardAnimationCurve) { [weak self] in
        self?.view.layoutIfNeeded()
    }
    
    animator.startAnimation()
} }
After implementation of all this steps you should have desired and reusable behaviour with configurable spacings.
Hope that helps!