问题描述
我试图找到一个方法来监视NSTextField的文本的变化。我尝试了 - (void)controlTextDidChange:(NSNotification *)obj
的委托方法,但它只有当用户输入到文本字段时才起作用。如果以编程方式设置文本字段字符串(例如使用按钮),则 controlTextDidChange
将不起作用。
I'm trying to find a method that monitors the text of NSTextField for changes. I tried the delegate method of -(void)controlTextDidChange:(NSNotification *)obj
but it only works when the user types into the text field. If the text field string is programmatically set, such as with a button, the controlTextDidChange
doesn't work.
有没有一个方法或另一种方法,我可以用来监视NSTextField的内容进行更改?
Is there a method or another approach that I can use to monitor the contents of a NSTextField for changes?
我的ButtonText类(设置为NSTextField的委托) p>
My ButtonText class (set as delegate for the 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显示按钮和文本字段:
The XIB showing the buttons and text field:
推荐答案
一种方法是使用KVO。特别是,添加 ButtonText
实例作为 buttonField
的观察者 stringValue
。
One approach is to use KVO. In particular, add the ButtonText
instance as an observer of buttonField
's stringValue
.
更详细地说,在 ButtonText
@property IBOutlet buttonField 已设置(即如果 ButtonText
是 NSWindowController
子类 -windowDidLoad
,如果 ButtonText
是 NSViewController
-loadView
),调用
In more detail, in your file ButtonText
, once the @property IBOutlet buttonField
has been set (i.e. if ButtonText
is an NSWindowController
subclass, in -windowDidLoad
, and if ButtonText
is an NSViewController
subclass in -loadView
), call
[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
写
Edit
Since ButtonText
is not a subclass of NSWindowController
or NSViewController
, we'll use a slightly different approach. As before, we'll want to start observing "once the @property IBOutlet buttonField
has been set". To do this, synthesize the property buttonField
to be the member variable mButtonField
writing
@synthesize buttonField = mButtonField;
并覆写 buttonField
:
- (void)setButtonField:(NSTextField *)buttonField
{
[self stopObservingButtonField];
mButtonField = buttonField;
[self startObservingButtonField];
}
我们需要确保 ButtonText
在释放按钮字段时停止观察,因此覆盖 -dealloc
如下:
We need to make sure that ButtonText
stops observing the button field when it deallocates as well, so override -dealloc
as follows:
- (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
变量。 (这不是真的,但如果我们设置 mButtonField
,我们必须确保首先停止观察其旧值的 @stringValue
键路径并开始观察它的新值的stringValue键路径。这样做而不是简单地调用 -setButtonField:
)
As a result of this arrangement, we must never set the mButtonField
variable outside of the -setButtonField:
method. (This isn't quite true, but if we do set mButtonField
we must be sure to first of all stop observing its old value's @"stringValue"
key path and start observing its new value's @"stringValue" key path. Doing this rather than simply calling -setButtonField:
would very likely simply constitute code repetition and not be worthwhile.)
如需参考,请参阅Apple的上的Cocoa / Reference / Foundation / Protocols / NSKeyValueObserving_Protocol / Reference / Reference.htmlrel =nofollow>文档。
For reference, check out Apple's documentation on the NSKeyValueObserving
protocol.
这篇关于ControlTextDidChange不适用于设置NSTextField的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!