HMDT - Logic and Intuition -

about HMDT

Cocoa Programming Tips 1001

Application Kit

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 つ気をつけてほしいのは、beginEditingendEditing を使うと、もっと効率的に編集が行われる、っていうこと。

Application Kit/NSTextStorage.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.gz

back to top content

Copyright © 2002-2006 HMDT. All rights reserved.