最近ではSwiftもVersion3になりましたね。
でも、あえてObjective-Cで。(Swift書けない)
カーソル位置を取得したい
UITextField(または、UITextView)で文字を打っているときのカーソルの位置を取得したいということがありました。
この青い線の場所です。
以下のようにすると取得できます。
UITextRange *textRange = textField.selectedTextRange;
UITextPosition *startPosition = textRange.start;
こんな感じでUITextPositionというクラスの値が取得できます。
UITextPosition…!?
UITextPositionとか扱いづらそうなので、int(NSInteger)に変換します。
UITextRange *textRange = textField.selectedTextRange;
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *startPosition = textRange.start;
NSInteger pos = [textField offsetFromPosition:beginning toPosition:startPosition];
これで、カーソルの位置が数値として得られます。
じゃあ、今度は追跡したい
次は、カーソルの位置が変わるたびに値を取得したいと思いました。
KVOを使います。
参考:[Objective-C] KeyValueObserve(キー値監視)メモ - Qiita
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[textField addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
UITextRange *textRange = textField.selectedTextRange;
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *startPosition = textRange.start;
NSInteger pos = [textField offsetFromPosition:beginning toPosition:startPosition];
}
これで、位置が変わるたびに取得できる!
と思ったのですが、文字を打った際には呼び出されませんでした…
UITextFieldのtextが書き換えられた時にメソッドを呼ぶ
UITextFieldのデリゲートメソッドを使います。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSInteger pos = range.location+string.length;
return YES;
}
これでいい感じです。(めんどくさくなったので、詳しい解説はしません。)
以上!
これで、カーソル位置を追跡。NSInteger型の値で取得できます。
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
[textField addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew context:nil];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
pos = range.location+string.length;
return YES;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
// ほんとだったらkeyPathできちんとチェックしてください…
UITextRange *textRange = _textField.selectedTextRange;
UITextPosition *beginning = _textField.beginningOfDocument;
UITextPosition *startPosition = textRange.start;
pos = [textField offsetFromPosition:beginning toPosition:startPosition];
}
より良い方法があれば教えてください…
参考URL
[Objective-C] KeyValueObserve(キー値監視)メモ - Qiita
the moon at dawn: UITextFieldのキャレットを操作(UITextRangeとUITextPosition)
ios - UITextPosition to NSRange - Stack Overflow