In my interface I have an NSTextField
who's value
is bound to an NSArrayController's
selection.selectedType.title
. All of the NSArrayController's
objects are custom objects each with two methods:
- (MYType *)selectedType;
- (void)setSelectedType: (MYType *)type;
The don't have an iVar selectedType
. However, they do have an iVar holding all MYType
objects. The code boils down to this:
- (MYType *)selectedType
{
if (someIndex == 0)
return [types objectAtIndex: 0];
else
return [self typeWithIndex: someIndex];
}
- (void)setSelectedType: (MYType *)type
{
someIndex = [type index];
}
MYType
objects got a NSString *title
iVar with a corresponding @property
and synthesize
.
Whenever I call setSelectedType:
, the changes are immediately visible in the NSTextField
and everything seems to work but I get a log message saying:
Cannot remove an observer NSArrayController 0x141160 for the key path "selectedType.title" from MYType 0x1a4830, most likely because the value for the key "selectedType" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the MYType class.
I tried encapsulating the setSelectedType:
method with willChangeValueForKey:
and didChangeValueForKey:
and then I still got a log message but a different one:
Cannot remove an observer NSKeyValueObservance 0x1c7570 for the key path "title" from MYType 0x1a4be0 because it is not registered as an observer.
First, use accessors. Don't access your ivars directly. You're bypassing the KVO for someIndex
because you modify the ivar directly. Don't touch ivars directly unless you have to.
You also need to let KVO know that selectedType
depends on someIndex
(and/or someStuff
; it's not clear from your distilled code).
+ (NSSet *)keyPathsForValuesAffectingSelectedType
{
return [NSSet setWithObjects:@"someIndex", nil];
}
This tells the KVO system that whenever someIndex
changes, it causes an implicit change in selectedType
. See Registering Dependent Keys.