One approach is to use KVO. In particular, add the ButtonText
instance as an observer of buttonField
's stringValue
.
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];
Define ButtonTextKVOContext
previously in the file as follows:
static int ButtonTextKVOContext = 0;
Then override observeValueForKeyPath:ofObject:change:context:
as follows:
- (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);
}
}
}
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;
and override buttonField
's setter as follows:
- (void)setButtonField:(NSTextField *)buttonField
{
[self stopObservingButtonField];
mButtonField = buttonField;
[self startObservingButtonField];
}
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];
}
It remains to define the methods -stopObservingButtonField
and -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];
}
}
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.)
For reference, check out Apple's documentation on the NSKeyValueObserving
protocol.