キーボードが表示されてカバーされているときに、UITextView のキャレットまでスクロールしようとしています。残念ながら、Apple が Notes アプリで同じことをしているにもかかわらず、アニメーション化しない場合にのみ機能します。Apple のドキュメントで説明されているのと同じアプローチを使用しています。
これがコードです。他の干渉なしにテストするために、隔離されたプロジェクトに配置されています。UITextView が追加された View Controller は 1 つだけです。シミュレーターとデバイスの両方で、iOS 7 でこれをテストしています。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedKeyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
}
- (void)receivedKeyboardDidShowNotification:(NSNotification *)notification {
CGRect keyboardBounds = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat keyboardDistanceFromBottomOfScreen = screenHeight - CGRectGetMinY(keyboardBounds);
UITextView *textView = self.textView;
UIEdgeInsets contentInset = textView.contentInset;
contentInset.bottom += keyboardDistanceFromBottomOfScreen;
textView.contentInset = contentInset;
textView.scrollIndicatorInsets = contentInset;
CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.end];
[textView scrollRectToVisible:caretRect animated:YES];
}
animated
最後の行のパラメーターを に設定するとNO
、これは完全に機能します (ただし、もちろんアニメーションは必要ありません)。渡すYES
と奇妙な動作が発生します。ほとんどの場合、ビューはスクロールしないか、数ピクセルしかスクロールしませんが、必要な動作が発生する場合があるため、結果はランダムです。
setContentOffset:animated:
キャレットのオフセットを計算して の代わりにメソッドを使用しようとしましたscrollRectToVisible:animated:
が、結果は同じです。の場合に機能しanimated
ますNO
。それを使用YES
すると、同じ奇妙な結果が生成されます。
さらに奇妙なことに、この 2 番目のソリューションでは、通知が 1 回しか配信されなかったにもかかわらず、その行のブレークポイントが 2 回ヒットしました。前の行またはその後に追加した行 (何もせず、テスト用のログ ステートメントのみ) のブレークポイントは 1 回だけヒットしました。さらに奇妙なことに、3 行にロギング ブレークポイントを配置すると、次の結果が得られました。
Line before
Buggy line
Line after
Buggy line
そのため、ラインの 2 番目のヒットは故障しました。インスペクタを見ると、すべてのローカル変数がスコープ外にあるように見えました。
また、両方のソリューションのコードを別のメソッドに入れて、遅延後に呼び出しようとしましたperformSelector:withObject:afterDelay:
が、1 秒のような長い遅延があっても何も変更されませんでした。最初のソリューションでは、このブレークポイントでのダブル ヒットは発生しませんでした。
この時点で私は解決策を使い果たしました。これは iOS のバグのように思えますが、前述したように Notes アプリで機能するため、少なくとも 1 つの解決策があります。
編集:さらに調査を行ったところ、テキストビューがファーストレスポンダーでキーボードが表示されている場合にのみバグが発生します(どちらが責任があるかはわかりません)。キーボード通知ではなくコードからトリガー scrollRectToVisible:animated:
すると、アニメーションは正常に機能します。しかし、最初[textView becomeFirstResponder]
にキーボードを表示する を呼び出すと、アニメーションが再び中断されます。