1

NSTextFieldのテキストの変更を監視するメソッドを見つけようとしています。のデリゲートメソッドを試しました-(void)controlTextDidChange:(NSNotification *)objが、ユーザーがテキストフィールドに入力した場合にのみ機能します。ボタンなどでテキストフィールド文字列がプログラムで設定されている場合、はcontrolTextDidChange機能しません。

NSTextFieldの内容の変更を監視するために使用できるメソッドまたは別のアプローチはありますか?

私のButtonTextクラス(NSTextFieldのデリゲートとして設定):

#import "ButtonText.h"

@interface ButtonText ()

@property (weak) IBOutlet NSTextField *buttonField;

@end

@implementation ButtonText

- (IBAction)buttonTextA:(id)sender {
    [_buttonField setStringValue:@"text A here"];
}

- (IBAction)buttonTextB:(id)sender {
    [_buttonField setStringValue:@"and text B stuff"];
}

- (void)controlTextDidChange:(NSNotification *)obj {
    NSLog(@"controlTextDidChange: %@", _buttonField.stringValue);
}

@end

ボタンとテキストフィールドを表示するXIB: ここに画像の説明を入力してください

4

2 に答える 2

1

1つのアプローチは、KVOを使用することです。特に、インスタンスを'sのButtonTextオブザーバーとして追加します。buttonFieldstringValue

より詳細には、ファイルButtonTextで、@property IBOutlet buttonFieldが設定されたら(つまり、ButtonTextNSWindowControllerサブクラスの場合、で-windowDidLoad、の場合ButtonTextがのNSViewControllerサブクラスである場合-loadView)、を呼び出します。

[self.buttonField addObserver:self
                   forKeyPath:@"stringValue"
                      options:0
                      context:&ButtonTextKVOContext];

ButtonTextKVOContext以前にファイルで次のように定義します。

static int ButtonTextKVOContext = 0;

次に、次のようにオーバーライドobserveValueForKeyPath:ofObject:change:context:します。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context != &ButtonTextKVOContext) {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        return;
    }

    if (object == self.buttonField) {
        if ([keyPath isEqualToString:@"stringValue"]) {
            NSLog(@"controlTextDidChange: %@", _buttonField.stringValue);
        }
    }
}

編集

ButtonTextはまたはのサブクラスではないNSWindowControllerため、NSViewController少し異なるアプローチを使用します。以前と同じように、「設定されたら」の観察を開始したいと思います@property IBOutlet buttonField。これを行うには、プロパティbuttonFieldを合成してメンバー変数mButtonFieldを書き込みます

@synthesize buttonField = mButtonField;

buttonField次のようにのセッターをオーバーライドします。

- (void)setButtonField:(NSTextField *)buttonField
{
    [self stopObservingButtonField];
    mButtonField = buttonField;
    [self startObservingButtonField];
}

ボタンフィールドの割り当てが解除されたときにもボタンフィールドの監視が停止することを確認する必要があるため、次ButtonTextのようにオーバーライド-deallocします。

- (void)dealloc
{
    [self stopObservingButtonField];
}

メソッドを定義すること-stopObservingButtonField-startObservingButtonField

- (void)stopObservingButtonField
{
    if (mButtonField) {
        [mButtonField removeObserver:self
                          forKeyPath:@"stringValue"
                             context:&ButtonTextKVOContext];
    }
}

- (void)startObservingButtonField
{
    if (mButtonField) {
        [self.buttonField addObserver:self
                           forKeyPath:@"stringValue"
                              options:0
                              context:&ButtonTextKVOContext];
    }
}

この配置の結果として、メソッドmButtonFieldの外部に変数を設定してはなりません。-setButtonField:(これは完全に真実ではありませんが、設定mButtonFieldする場合は、まず最初に古い値のキーパスの監視を停止し@"stringValue"、新しい値の@ "stringValue"キーパスの監視を開始する必要があります。単に呼び出すのではなく、これを行う-setButtonField:可能性が非常に高くなります。単にコードの繰り返しを構成するだけで、価値はありません。)

参考までに、プロトコルに関するAppleのドキュメントをNSKeyValueObserving確認してください。

于 2012-10-30T05:08:49.120 に答える
0

バインディングを使用することが目的の場合は、テキストフィールドの値にバインドしたプロパティのsetterメソッドをオーバーライドして、そこで実行したい監視を行うことができます。したがって、たとえば、値がプロパティmyTextにバインドされているテキストフィールドがある場合、次のように実行できます。

-(void)setMyText:(NSString *) newValue {
    _myText= newValue;
    // do monitoring here
}

これは、ivarに直接アクセスするのではなく、プロパティを介して行う限り、ユーザーがテキストフィールドに入力するか、コードの値を変更するたびに呼び出す必要があります。

于 2012-10-30T04:38:35.887 に答える