55486


ストリーボードに素朴に`UITextView`を置いています。

下記コードを試したところ、1回目のキーボードの高さは`print`で確認したところ`346.0`でしたが、2回目は`288.0`。

表示されたキーボードは同じ見た目ですので、高さ（`keyboardSize.height`）が変わった理由がわかりません。何故高さが変わるのでしょうか？

もしくは正しい、高さの取得方法は別にありますか？

[code]

    import UIKit
    
    class ViewController: UIViewController, UITextViewDelegate {
        @IBOutlet weak var hogeTextView: UITextView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.hogeTextView.delegate = self
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        }
    
        @objc func keyboardWillShow(notification: NSNotification) {
            guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else  { return }
    
            print(keyboardSize.height)
        }
    
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    
            if (text == "\n") {
                hogeTextView.resignFirstResponder()
                return false
            }
            return true
        }
    }
    
[/code]


CC BY-SA 4.0
2019-06-03T07:39:59.877
55478
2019-06-03T12:00:22.723
9008
question
swift ios
キーボードの高さが２回目以降で縮む


[`keyboardFrameBeginUserInfoKey`のドキュメント](https://developer.apple.com/documentation/uikit/uiresponder/1621616-keyboardframebeginuserinfokey)にはこう書いてあります。

> The key for an `NSValue` object containing a `CGRect` that identifies  
>  the **starting frame** rectangle of the keyboard in screen coordinates.  
>  The frame rectangle reflects the current orientation of the device.

似たようなキーで、[`keyboardFrameEndUserInfoKey`の方](https://developer.apple.com/documentation/uikit/uiresponder/1621578-keyboardframeenduserinfokey)はこんな風:

> The key for an `NSValue` object containing a `CGRect` that identifies  
>  the **ending frame** rectangle of the keyboard in screen coordinates. The  
>  frame rectangle reflects the current orientation of the device.

(太字化は回答者。)

ここでの **starting frame** , **ending frame**
とは、キーボードの表示/消去のアニメーションの開始時のフレーム、終了時のフレームを表していると考えられます。

iOSのキーボードは画面下部からニューっと上がってくる感じですが、画面の外にある時(`keyboardFrameBeginUserInfoKey`用のフレームが取得される時)には、iOSはその高さには無頓着で、キーボード用のviewの高さをちゃんと設定していないのだと思われます。手元のiOS
7 Plus simulatorで試したら、1回目は0.0と表示されることが多かったです。

これからキーボードが表示される(あるいは「表示された」)と言うイベントでは、`keyboardFrameEndUserInfoKey`の方が、「表示されたキーボード」のフレームを表していると考えられます。次のように`userInfo`を取得する時のキーを変えてみてください。

[code]

    guard let keyboardSize = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else  { return }
    
[/code]

(ついでに、`CGRect`を保持する`NSValue`は、直接`as?`キャストでSwift側`CGRect`にブリッジ可能なので、その点もコードに反映させていますが、肝はキーが`UIResponder.keyboardFrameEndUserInfoKey`になっていることの方です。)

コードをこのように書き換えれば、常に「キーボード表示アニメーション終了時のフレーム」から高さを取得するので、デバイスの画面サイズに応じた一定の値を返すと思うのですが?
お試しください。


CC BY-SA 4.0
2019-06-03T12:00:22.723
55486
2019-06-03T12:00:22.723
13972
55478
answer