Why is trying to animate UIView to sync with keyboard popup not working?

114 Views Asked by At

I am trying to get a UIView to move up in sync with my keyboard when it is opened so the typing field remains in the display when the keyboard is up. However, while it does seem like the frame of the view is being updated in the code, the animation doesn't show in the simulator. The code is show below. I am working in XCode 12 and doing this fully programatically (no storyboards). This function activates whenever the notification for the keyboard opening is posted. The output of this is as follows:

showing keyboard

begin

(0.0, 528.96, 375.0, 88.16)

end

(0.0, 528.96, 375.0, 88.16)

this should be changed

(0.0, 237.96000000000004, 375.0, 379.15999999999997)

end

(0.0, 237.96000000000004, 375.0, 379.15999999999997)

@objc private func keyboardWillShow(notification: NSNotification) {
    print("showing keyboard")

    let userInfo: NSDictionary = notification.userInfo! as NSDictionary
    let keyboardFrame: NSValue = userInfo.value(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue
    let keyboardRectangle = keyboardFrame.cgRectValue
    let keyboardHeight = keyboardRectangle.height
    let commentViewSize: CGFloat = view.height/7

    print("begin")
    print(commentFieldView.frame)

    UIView.animate(withDuration: 0.1, delay: 0, animations: { [weak self] in
        guard let strongSelf = self else {
            return
        }

        DispatchQueue.main.async {
            strongSelf.commentFieldView.frame = CGRect(x: 0, y: strongSelf.view.height - commentViewSize - keyboardHeight, width: strongSelf.view.width, height: commentViewSize + keyboardHeight)

            strongSelf.profilePic.frame = CGRect(x: strongSelf.commentFieldView.left + 15, y: strongSelf.commentFieldView.height/5, width: 100, height: 100)

            print("this should be changed")
            print(strongSelf.commentFieldView.frame)
        }
    }) { _ in
        print("end")
        print(self.commentFieldView.frame)
    }

    print("end")
    print(self.commentFieldView.frame)
}
1

There are 1 best solutions below

0
HangarRash On

The problem is the use of DispatchQueue.main.async inside UIView.animate. That prevents that code from being animated. The keyboard notification will only be called on the main queue and the code inside animation block will be called on the same queue that you call UIView.animate on.

UIView.animate(withDuration: 0.1) {
    self.commentFieldView.frame = CGRect(x: 0, y: self.view.height - commentViewSize - keyboardHeight, width: self.view.width, height: commentViewSize + keyboardHeight)

    self.profilePic.frame = CGRect(x: self.commentFieldView.left + 15, y: self.commentFieldView.height/5, width: 100, height: 100)
}