• 키보드의 동작을 notification을 통해 감지하고, 그때 레이아웃 등의 변화를 적용


private func addKeyboardNotifications() {
    NotificationCenter.default.addObserver(self,
                                         selector: #selector(keyboardWillShow(_:)),
                                         name: UIResponder.keyboardWillShowNotification,
                                         object: nil)
    NotificationCenter.default.addObserver(self,
                                         selector: #selector(keyboardWillHide(_:)),
                                         name: UIResponder.keyboardWillHideNotification,
                                         object: nil)
}

private func removeKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self,
                                            name: UIResponder.keyboardWillShowNotification,
                                            object: nil)
    NotificationCenter.default.removeObserver(self,
                                            name: UIResponder.keyboardWillHideNotification,
                                            object: nil)
}

addKeyboardNotifications() 에서

NotificationCenter addObserver 를 통해 키보드가 화면 위로 올라왔을때, 내려갈때를 감지할 수 있도록 등록해주었습니다.

removeKeyboardNotifications() 에서는 removeObserver 를 통해 해당 화면이 사라질때 메모리에서 해제해주어 메모리 누수를 방지해두었습니다.

    @objc private func keyboardWillShow(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
              let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
              let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else { return }

        let keyboardHeight = keyboardFrame.height
        self.customTextViewBottomConstraint?.update(offset: -3)

        UIView.animate(withDuration: duration) {
            self.view.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight)
            self.textView.movePlusButtonToBottom(true)
        }
    }

    @objc private func keyboardWillHide(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
              let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else { return }
        self.customTextViewBottomConstraint?.update(offset: 0)
        UIView.animate(withDuration: duration) {
            self.view.transform = .identity
            self.textView.movePlusButtonToBottom(false)
        }
    }

키보드가 올라오고 내려오는 동작을 감지할때 실행되는 함수들을 정의해 둔 곳입니다.

keyboardFrame.height를 통해 기기 자체의 keyboard 높이를 받아서 변수에 저장한 후, view의 y frame 값을 -(키보드 높이) 만큼 해주고 되돌려서 키보드 높이 위로 해당 화면이 올라갔다 내려갔다 하도록 레이아웃을 설정해 두었습니다.

private func setupDismissKeyboardGesture() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    tapGesture.cancelsTouchesInView = false
    view.addGestureRecognizer(tapGesture)
}

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

이 함수를 통해, 키보드가 올라왔을때 다른 화면을 touch 하면 키보드가 내려갈 수 있도록 설정해두었습니다.

view.endEditing(true) 은 view 또는 그 하위 뷰 중 first responder가 있으면 이를 resign 시켜 키보드를 내리는 함수라고 합니다.