NSTextStorage

NSTextStorage

Application Kit - NSTextStorage

NSTextStorage とは

Keywords: NSTextStorage, text handling

NSTextStorage ってのは、NSTextView を使ってテキストを取り扱うときに使われるクラスなんだ。主な役目は次の通り:

・テキストを保持する
 NSTextStorage が実際のテキストデータを保持するんだ。このクラスは NSMutableAttributedString を継承してるクラスだから、そっからも分かるよな。

・NSLayoutManager の参照を保持する
 テキスト編集クラスの次の階層である、NSLayoutManager への参照を持っているんだ。複数持つことができるよ。

・テキストの変更を受け取る、通知する
 ユーザが NSTextView に文字を打ち込んだりすると、その編集情報がこのクラスまでやってくるんだ。それを取り扱う。あと delegate にそのイベントを通知したりするんだ。




Application Kit - NSTextStorage

NSTextStorage をプログラムから変更する

Keywords: beginEditing, endEditing

NSTextStorage が保持しているテキストを、プログラムの内部で変更することを考えてみよう。実際には、文字を変更するメソッドが定義されているのは NSTextStorage ではなくて、その親クラスの NSMutableAttributedString だ。NSMutableAttributedString にある、文字変更メソッドや、属性変更のためのメソッドを使うんだ。

1 つ気をつけてほしいのは、beginEditing と endEditing を使うと、もっと効率的に編集が行われる、っていうこと。

Application Kit/NSTableColumn.h

- (void)beginEditing;
- (void)endEditing;

NSTextStorage ではテキストが変更されたら、NSTextLayout を呼んで、NSTextView の画面の表示を変更しないといけない。でも、毎回やってたら遅くなるわな。それをコントロールすることができるんだ。

テキストを変更する前に、beginEditing を呼んでおく。そうすると、その後の変更はとりあえずバッファに突っ込まれて、まだ NSTextLayout に通知されないんだ。変更が終わったら endEditing を呼ぶ。その時点で、NSTextStorage は変更を処理して、上のレイヤに通知するんだ。そこんとこ注意。




Application Kit - NSTextStorage

テキストが編集された通知を受け取る

Keywords: NSTextStorageDelegate

NSTextView を使ってテキストを編集すると、編集の情報が階層を伝って NSTextStorage までやってくるんだ。NSTextStorage はそれをもとに、自分が持っているテキストデータを変更する。そのイベントを delegate が受け取ることができるんだ。

NSTextStorage は、テキストを変更するときに次の 2 つのメッセージを投げる。

Application Kit/NSTextStorage.h

- (void)textStorageWillProcessEditing:(NSNotification *)notification;
- (void)textStorageDidProcessEditing:(NSNotification *)notification;

当然、変更前が textStorageWillProcessEditing: で、後が textStorageDidProcessEditing: だな。これで、テキスト変更のイベントを受け取ることができるぜ。

じゃ、次の質問。どこが変更されたかを知るには?それには NSTextStorage の次のメソッドを使う。

Application Kit/NSTextStorage.h

- (unsigned int)editedMask;
- (NSRange)editedRange;
- (int)changeInLength;

editedMask は、何が変更されたかを調べる。属性か?文字か?その両方か?editedRange は、変更された範囲。changeInLength は何文字が変更されたかだ。文字が挿入されたときはプラスの値。削除されたときはマイナスの値だ。

では、サンプルを見てみよう。


MyDocument.m (sample)

- (void)textStorageDidProcessEditing:(NSNotification*)notification
{
 NSTextStorage* textStorage = [_textView textStorage];

 unsigned int mask = [textStorage editedMask];
 NSRange range = [textStorage editedRange];
 int length = [textStorage changeInLength];

 if (mask & NSTextStorageEditedAttributes) {
  NSLog(@"Edited mask: NSTextStorageEditedAttributes");
 }
 if (mask & NSTextStorageEditedCharacters) {
  NSLog(@"Edited mask: NSTextStorageEditedCharacters");
 }

 NSLog(@"Edited range: location=%d, length=%d",
    range.location, range.length);

 NSLog(@"Change in length: %d", length);
}

ここでは textStorageDidProcessEditing: の中で、編集情報を表示させている。プログラムを走らせて、テキストビューに文字を打ち込む度に、このメソッドが呼び出されるのが確認できるはずだよ。

■サンプルダウンロード:
TextStorageDelegate.tar




Application Kit