Web・IT うんたらら

業務系とWeb系の狭間でIT業界を彷徨いながら備忘録と足跡を残していきます

【Objective-C】UITextFieldのキャレット(カーソル)操作あれこれ

UITextViewには比較的直感的にキャレット位置を取得できるselectedRangeプロパティがありますが、UITextFieldには数値としての位置情報を持たないselectedTextRangeプロパティしかないため、単純に現在位置を取得したり、指定位置に移動させたりするのも一苦労です。

調べたところ、日本語の情報がないようだったのでメモ。
以下は、StackOverflowから拝借したコードを整理したものです。

//キャレット位置セット
- (void)selectTextForInput:(UITextField *)input atRange:(NSRange)range
{
    UITextPosition *start = [input positionFromPosition:[input beginningOfDocument] offset:range.location];
    UITextPosition *end = [input positionFromPosition:start offset:range.length];
    [input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];
}
//キャレット位置取得
- (NSInteger)getCaretLocationForInput:(UITextField *) input
{
    UITextRange *selRange = input.selectedTextRange;
    UITextPosition *selStartPos = selRange.start;
    return [input offsetFromPosition:input.beginningOfDocument toPosition:selStartPos];
}


これをさらにObjective-Cらしく、再利用可能にするためカテゴリ化したものが以下。

UITextField+ControlCaret.h
#import <UIKit/UIKit.h>

@interface UITextField (ControlCaret)

- (void)selectTextAtRange:(NSRange)range;
- (NSInteger)getCaretLocation;

@end
UITextField+ControlCaret.m
#import "UITextField+ControlCaret.h"

@implementation UITextField (ControlCaret)

- (void)selectTextAtRange:(NSRange)range
{
    UITextPosition *start = [self positionFromPosition:[self beginningOfDocument] offset:range.location];
    UITextPosition *end = [self positionFromPosition:start offset:range.length];
    [self setSelectedTextRange:[self textRangeFromPosition:start toPosition:end]];
}

- (NSInteger)getCaretLocation
{
    UITextRange *selRange = self.selectedTextRange;
    UITextPosition *selStartPos = selRange.start;
    return [self offsetFromPosition:self.beginningOfDocument toPosition:selStartPos];
}

@end


...カテゴリの命名規則ってこんな感じで良いのでしょうか。
よく、「元クラス名+カテゴリ名」と記載されていますが、そのカテゴリ名部分が知りたいんだよ!というね。