ControlTextDidChange不适用于设置NSTextField的字符串

时间:2012-10-29 22:31:21

标签: objective-c cocoa nstextfield nscontrol

我正在尝试查找监视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显示按钮和文本字段: enter image description here

2 个答案:

答案 0 :(得分:1)

一种方法是使用KVO。特别是,将ButtonText实例添加为buttonField的{​​{1}}的观察者。

更详细地说,在您的文件stringValue中,一旦ButtonText被设置(即如果@property IBOutlet buttonFieldButtonText子类,则在NSWindowController中,如果-windowDidLoadButtonText中的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); } } } 不是ButtonTextNSWindowController的子类,我们将采用稍微不同的方法。和以前一样,我们要开始观察“一旦设置NSViewController”。为此,请将属性@property IBOutlet buttonField合成为成员变量buttonField编写

mButtonField

并覆盖@synthesize buttonField = mButtonField; 的setter,如下所示:

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"很可能只会构成代码重复而不值得。)

作为参考,请查看Apple的documentation on the NSKeyValueObserving protocol

答案 1 :(得分:0)

如果您的目标是使用绑定,那么您可以覆盖绑定到文本字段值的属性的setter方法,并执行您想要执行的任何监视。因此,例如,您有一个文本字段,其值绑定到属性myText,那么您可以执行以下操作:

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

只要您通过属性进行操作,而不是直接访问ivar,就应该在用户输入文本字段或更改代码中的值时调用此方法。