6 macos cocoa objective-c key-value-observing
我的模型类大多是用合成的setter/getter方法实现的,一切都很好.一切都很好地连接到用户界面.后来我才意识到,改变一个属性应该引起其他性质改变(改变type
可能导致的变化minA
和maxA
),所以我手动写的二传手/ getter方法type
属性.代码如下:
QBElementType
@interface QBElementType : NSObject
@property NSRange minRange;
@property NSRange maxRange;
@end
@implementation QBElementType
@synthesize minRange;
@synthesize maxRange;
@end
Run Code Online (Sandbox Code Playgroud)
QBElement
@interface QBElement : QBElementType{
QBElementType *_type;
}
@property (weak) QBElementType *type;
@property NSUInteger minA;
@property NSUInteger maxA;
@end
@implementation QBElement
@synthesize minA = _minA;
@synthesize maxA = _maxA;
- (QBElementType*)type
{
return _type;
}
- (void)setType:(QBElementType*)newType
{
[self willChangeValueForKey:@"type"];
_type = newType; // no need to bother with retain/release due to ARC.
[self didChangeValueForKey:@"type"];
/* Having the following 4 lines commented out or not changes nothing to the error
if (!NSLocationInRange(_minA, newType.minRange))
self.minA = newType.minRange.location;
if (!NSLocationInRange(_maxA, newType.maxRange))
self.maxA = newType.maxRange.location;
*/
}
@end
Run Code Online (Sandbox Code Playgroud)
问题:从那时起,每当我更改Element的Type时,我都会得到一个未被捕获的异常:
无法为观察者<NSTableBinder ...>更新来自<QBElement ...>的密钥路径"type.minRange",很可能是因为更改了密钥"type"的值而没有发送适当的KVO通知.检查QBElement类的KVO-Compliance.
KVO-Compliance是否遗漏了一些明显的东西?为什么我会收到此错误?
您不需要显式调用-willChangeValueForKey:
and-didChangeValueForKey:
因为您的 setter 已正确命名。对它们的调用将通过 KVC/KVO 机制的魔力自动添加。问题可能在于它们实际上被调用了两次。
另外,由于minA
和maxA
看起来只是从类型派生而来,因此您可以将它们设置为只读,并告诉 KVO 自动通知观察者 minA 和 maxA 已在任何时间发生变化type
:
@interface QBElement : QBElementType{
QBElementType *_type;
}
@property (weak) QBElementType *type;
@property (readonly) NSUInteger minA;
@property (readonly) NSUInteger maxA;
@end
@implementation QBElement
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"minA"] ||
[key isEqualToString:@"maxA"]) {
keyPaths = [keyPaths setByAddingObject:@"type"];
}
return keyPaths;
}
@synthesize type;
- (NSUInteger)minA
{
return self.type.minRange.location;
}
- (NSUInteger)maxA
{
return self.type.maxRange.location;
}
@end
Run Code Online (Sandbox Code Playgroud)