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

一种方法是使用 KVO。特别是,将实例添加为'sButtonText的观察者。buttonFieldstringValue

更详细地说,在您的文件中,ButtonText一旦@property IBOutlet buttonField设置ButtonTextNSWindowController-windowDidLoadButtonTextNSViewController-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不是 or 的子类NSWindowControllerNSViewController我们将使用稍微不同的方法。和以前一样,我们希望“一旦@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 回答