You are here: Home / TinBlog / UITextInputえくすとら

UITextInputえくすとら

Posted by h2 at Dec 28, 2010 06:30 PM |
Filed under: ,
諸々が年末進行しているせいで、時間的余裕が・・・試したいことばかりが山積みになる今日この頃。 休みにはいったら、一気に消化したいなあとか企みつつも、その前に、もう一度しつこくUITextInput。

いろいろ問題の多いクラスだが、それ以上に組み方がよくわからないクラスのせいだろうか、迷っている人がちらほらいるらしいので、も一度簡単に実装方法をおさらいしておこうかと。時間があれば、サンプルでも作りたいところなのだが。というわけで、とりあえず簡単に手順だけを。

 

1. UITextPositionを継承したサブクラスを自作

@interface MyTextPosition : UITextPosition <NSCopying> {
    int  position;
    BOOL beginningOfText;
    BOOL endOfText;
}
@property (readonly) int position;
@property (readonly) BOOL beginningOfText;
@property (readonly) BOOL endOfText;
@end

テキストの位置を指定するためのクラス。CGPointのようなノリのものだが、複雑な構造の文書や不可視文字などに対応させるために、クラスになっている。最も単純なプレーンテキストの場合は、単に「何文字目か」のインデックスだけ持っていればよい。ついでに「文章の終端(EOFみたいに)」や「文章の先頭(最初の文字よりも手前)」などの指定ができるようにしておくと、あとあと仕掛けが組みやすい。(ここではBOOLとして端折っているが、メモリコストを考えつつ、よさげな実装でど〜ぞ)

また、後々作業をやりやすくするためにも、NSCopyingのプロトコルを実装しておくことをおすすめする。

 

2. UITextRangeを継承したサブクラスを自作

@interface MyTextRange : UITextRange <NSCopying> {
    MyTextPosition *start;
    MyTextPosition *end;
    BOOL           empty;
}
@property (readonly, getter=isEmpty) BOOL empty;
@property (readonly) UITextPosition *start;
@property (readonly) UITextPosition *end;
@end

テキストの範囲を決めるクラス。メンバーには、自作のUITextPositionを継承したサブクラスを用意するのだが。このクラスが、意外と注意点が多い。

まず一点目。UITextRangeではUITextPosition形式でのpropertyが要求されているので、外部に紐付けする際はMyTextPositionをダウンキャストしたものを使用する。早い話が、@synthesizeを使用せずに、自力でメソッド作成しろよ、と。どーしても@synthesizeにこだわるのなら、メンバー宣言はUITextPositionとしておいて、実体はMyTextPosition、という手もある。

二点目。リファレンスでの指定はないが、あからさまにNSCopyingプロトコルを実装しておくべきらしいので、こいつを実装。

三点目。この後出てくるUITextInputを利用する側のクラスだが、どうやら所々で「startendnilではない」ことを前提として動いている節があったりするんだな、これが。なので、UITextRangeのインスタンスを生成する場合は、必ずstartendが有る状態にしておいた方がよい。だが、こうしてしまうと、「1文字選択されている」のか「位置だけで選択範囲が0」なのかの区別がつかなくなる。別の場所で管理しても良いのだが、ここにemptyフラグ付けちゃった方が楽かと。

 

3. UITextInputを継承したビューを作成

@interface MyTextView : UIView <UITextInput, UITextInputTraits> {
    MyTextRange     *selectedTextRange;
    MyTextRange     *markedTextRange;
    MyTextPosition  *beginningOfDocument;
    MyTextPosition  *endOfDocument;
    id <UITextInputDelegate> inputDelegate;
    .... (以下略)
}
@property (readwrite, copy) UITextRange *selectedTextRange;
@property (nonatomic, readonly) UITextRange *markedTextRange;
.... (以下略)
@end

このクラスについては、リファレンスとヘッダーファイル(UITextInput.h)のコメント読みつつ進めていけば、それほど迷わずに済むのではないかと。

ここでも、外部にpropertyしているselectedTextRange等はUITextRange希望、なので、MyTextRangeの時と同様にメソッドを自作するなり(以下略。

あと、キー入力対応させるために、canBecomeFirstResponderを実装することと、タッチ時にカーソル位置を制御したりするためにtouchesBeganを書き書きしたりする必要がある。

 

あとは、できあがったMyTextViewを、InterfaceBuilderでぺたりと貼り付けるなりすれば、お手軽なボク仕様テキストビュー完成。

 

 

Filed under: ,
« August 2019 »
August
SuMoTuWeThFrSa
123
45678910
11121314151617
18192021222324
25262728293031