我需要在使用KVO的Objective-C类上观察union-typed属性,但似乎我没有运气。我做了一些实验:只要我使用的是C结构,一切正常。只要我用结合替换结构,自动KVO就不再起作用了(observeValueForKeyPath
没有被调用)。
这是我的小型测试课程:
AppDelegate.h:
#import <Cocoa/Cocoa.h>
typedef union {
float data[3];
struct {
float x,y,z;
};
} vec3union;
typedef struct {
float x,y,z;
} vec3struct;
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@property (assign) vec3struct vectorStructValue;
@property (assign) vec3union vectorUnionValue;
@end
AppDelegate.m:
@implementation AppDelegate
@synthesize vectorStructValue = _vectorStructValue;
@synthesize vectorUnionValue = _vectorUnionValue;
- (void)dealloc
{
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self addObserver:self forKeyPath:@"vectorStructValue" options:NSKeyValueObservingOptionNew context:nil];
[self addObserver:self forKeyPath:@"vectorUnionValue" options:NSKeyValueObservingOptionNew context:nil];
self.vectorStructValue = (vec3struct){1,2,3};
self.vectorUnionValue = (vec3union){4,5,6};
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"keyPath %@ did change, object: %@", keyPath, [object description]);
}
@end
输出:
2013-01-12 17:38:26.447 KVOTest[57522:303] keyPath vectorStructValue did change, object: <AppDelegate: 0x100614200>
我做错了什么,或者这是Objective-C运行时/ KVO实现中的错误或遗漏功能?
注意:我知道我可以通过覆盖属性设置器手动实现它,但这不是这个问题的重点。答案应该让我知道为什么自动KVO在这种情况下不起作用。
更新:为了清楚说明,这是一个简单的测试用例,它将struct属性上的KVO观察者与union属性上的KVO观察者进行比较。这些属性不相关。他们有独立的ivars和独立的内存支持商店。您可以删除struct属性并运行测试,结果仍然相同 - union属性没有KVO观察者事件。
答案 0 :(得分:10)
工会在KVO / KVC中被淘汰出局。留下下面的文字,因为它仍然很有趣。
KVO无法通过观察记忆或播放任何此类棘手的诡计而起作用。它的工作原理是动态创建一个子类,覆盖setter方法,并在调用setter时自动调用willChange.../didChange...
方法。
因此,您实际上拥有 2个 1个支持商店。然而,就KVO而言,它们完全相互隔离。
你想要的是依赖键。您可以使用+keyPathsForValuesAffectingValueForKey:
在两个键之间创建依赖关系,这样调用setter就会触发另一个属性的更改。
我不知道它是否支持共同依赖;如果它支持有效的循环依赖。
或者,你应该能够覆盖setter来为另一个属性(以及被更改的属性)调用willChange/didChange
。
如果要么属性发生更改,如果您希望{em} 键触发willChange/didChange
,则会使用相关的密钥。即如果你搞砸了struct,那么union会有效地改变,union属性的观察者应该看到一个意愿/做了改变,以响应设置结构版本。
我刚试过它。你是对的。工会有点奇怪。它破碎了。所有这些仍然是正确的,但它没有好处。
雷达提交:rdar:// problem / 13003794
vectorUnionValue
的密钥。
我补充说:
+ (NSSet *)keyPathsForValuesAffectingVectorStructValue
{
return [NSSet setWithObject:@"vectorUnionValue"];
}
+ (NSSet *)keyPathsForValuesAffectingVectorUnionValue
{
return [NSSet setWithObject:@"vectorStructValue"];
}
导致运行时异常:
2013-01-12 12:05:11.877 djkdfjkdfjkdf[51598:303] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppDelegate 0x10010a520> valueForUndefinedKey:]: this class is not key value coding-compliant for the key vectorUnionValue.'