Search code examples
iosswiftautolayout

Swift 5 - Editing Text Field Hides Keyboard


I'm having some trouble with auto-layout and moving the view upwards when a keyboard is displayed on screen for iOS as it gets covered up. Looking online there are various solutions but the most common is using the Notification Centre to get the size of the keyboard and animate the view. I've created an IBOutlet for a constraint to be changed but I keep getting an error Value of type 'UIView' has no member 'passwordBottom'.

Can anyone help with where I am going wrong?

class LoginViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var usernameBottom: NSLayoutConstraint!
    @IBOutlet weak var passwordBottom: NSLayoutConstraint!
    @IBOutlet weak var usernameTF: UITextField!
    @IBOutlet weak var passwordTF: UITextField!

    var offsetY:CGFloat = 0

    @IBAction func signinPressed(_ sender: Any) {
    }

    @IBAction func forgotPasswordPressed(_ sender: Any) {
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow(notification:)), name:  UIResponder.keyboardWillShowNotification, object: nil )
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    }

    @objc func keyboardWillShow( notification: Notification) {
        if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
            let newHeight: CGFloat
            let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
            let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
            if #available(iOS 11.0, *) {
                newHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
            } else {
                newHeight = keyboardFrame.cgRectValue.height
            }
            let keyboardHeight = newHeight  + 10
            UIView.animate(withDuration: duration,
                           delay: TimeInterval(0),
                           options: animationCurve,
                           animations: {
                            self.view.passwordBottom.constant = keyboardHeight
                            self.view.layoutIfNeeded() },
                           completion: nil)
        }
    }  
}

Solution

  • passwordBottom is an attribute from your VC, not your view.

    Change : self.view.passwordBottom.constant = keyboardHeight

    into: self.passwordBottom.constant = keyboardHeight