【Swift】キーボード表示時にviewを移動させる処理で詰まったこと(メモ)


症状

textFieldをタップした際にいい感じにviewを上に移動させたいが下記のような状態になってしまう。

本当は上に動くようにしたいのに、viewが下に動いてしまって何も見えなくなってしまっています・・・

この部分の処理はこんな感じ↓(ViewdidLoadでsetUpNotificationForTextField()を読んで使用している)

    func setUpNotificationForTextField() {
        let notificationCenter = NotificationCenter.default
        // キーボードが出る時に呼ばれる
        notificationCenter.addObserver(self, selector: #selector(self.keyboardWillShow(_ :)),
                                       name:UIResponder.keyboardWillShowNotification, object: nil)
        // キーボードが隠れる時に呼ばれる
        notificationCenter.addObserver(self, selector: #selector(self.keyboardWillHide(_ :)),
                                       name:UIResponder.keyboardWillHideNotification, object: nil)
    }

    // キーボードが出てきた時の処理
    @objc func keyboardWillShow(_ notification: Notification) {
        // キーボードのMinYを取得
        let keyboardFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
        guard let keyboardMinY = keyboardFrame?.minY else { return }

        // doneBtnのmaxYを取得
        let btnMaxY = doneBtn.frame.maxY

        // 動きを登録
        let distance = btnMaxY - keyboardMinY + 60
        let transform = CGAffineTransform(translationX: 0, y: -distance)

        // アニメーション
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [], animations: {
            self.view.transform = transform
        })
    }

    //キーボードが隠れた時の処理
    @objc func keyboardWillHide(_ notification: Notification) {
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [], animations: {
            self.view.transform = .identity
        })
    }

上記でコードを載せたはいいが他画面では、ほぼ同じ処理で正常に動作しているのでコードが原因ではなさそう・・・

原因

原因は下記の赤枠部分をstackViewに入れているからでした。

下の部分のコードは、下記画像の赤色部分ように画面上部からdoneBtnの下部までの距離を取得するのが意図でしたが、ボタンをstackViewに入れることで下記画像の緑部分のように、stackViewの上部からdoneBtnの下部までの距離を取得してしまっていたことが今回の症状の原因でした。

二つのボタンをstackViewから出してあげることで正常に動作しました。

// doneBtn(チェックマークのボタン)のmaxYを取得
        let btnMaxY = doneBtn.frame.maxY

わかったこと

UI部品のMaxY, MinY , MaxX, MinXは親viewを基準にしている(間違っていたらすみません)

以上です。