iOSのアプリでキーボードの通知を監視する

こんにちは、JAGA(ja_gaimopotato)です。
iOSのアプリを開発していて、テキスト入力のイベントの各種タイミングを知ったりキーボードのサイズを取得して、あれこれするということは、iOSアプリを作りはじめてすぐに気になったことでした。

色々と失敗しては、メモをして、ということを繰り返しながら知識を貯めているのですが、キーボードのサイズを取得する時に少しミスとしていたことがありました。

キーボード関連の通知を監視する

UITextViewのキーボードの表示、非表示の通知を受ける場合は、UIWindowで定義されているUIKeyboard関連の通知キーを関しすることで実装できます。

// キーボードの表示が始まる前
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification object:nil];

// キーボードの表示が終わったあと
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidShow:)
                                             name:UIKeyboardDidShowNotification object:nil];

// キーボードが非表示になる前   
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification object:nil];

// キーボードが非表示なったあと
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification object:nil];

// キーボードのサイズが変化するとき
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboarDidChangeFrame:)
                                             name:UIKeyboardDidChangeFrameNotification object:nil];

で通知を監視します。

それぞれの通知ごとに呼ばれるメソッドを設定してキーボードの状態によってViewのサイズを変化させていくことなどに対応できます。

一括登録 & 解除する

実際には、これらの通知を一括登録するメソッドでも作っておいて、テキストの編集開始時に監視します。

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{

    [self registerForKeyboardNotifications];

    return YES;
}

で、テキストの編集が終わったら監視も終了する方が良いので、一括で解除するメソッドを設定します。

- (void)removeAllKeyboardNotifications{

[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidChangeFrameNotification object:nil];

}

タイミングに注意しよう

これを呼ぶタイミングは、編集が終わったあとが良いのですが以下のように

- (void)textViewDidEndEditing:(UITextView *)textView{

    [self removeForKeyboardNotifications];
}

としてしまうと、UIKeyboardDidHideNotificationが得られないまま解除してしまいます。
ですので、UIKeyboardDidHideNotificationの通知を受けて呼ばれるメソッド内で通知を解除しなければなりません。 

この例で言えば以下のようにします。  

- (void)keyboardDidHide:(NSNotification *)notification{

[self removeAllKeyboardNotifications];

}

とすることで、キーボードの表示から非表示までの一連の動きを追うことができます。

ぼくが書いたコードではこのタイミングを間違っていたことで、keyboardDidHide:が呼ばれない状態になっていたのです。
UIKeyboardDidChangeFrameNotificationで無理やりサイズを取得して解決するという何とも無駄な労力をかけていました。
反省です。

これからも更新を続けていきますので、Feedlyへの登録をお願いします!

follow us in feedly

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です