【发布时间】:2013-01-12 16:47:14
【问题描述】:
我需要在使用 KVO 的 Objective-C 类上观察联合类型的属性,但我似乎没有运气。我做了一些实验:只要我使用 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 在这种情况下不起作用。
更新:为了清楚起见,这是一个简单的测试用例,将结构属性上的 KVO 观察者与联合属性上的观察者进行比较。这些属性不相关。他们有独立的 ivars 和独立的内存后备存储。您可以删除 struct 属性并运行测试,仍然是相同的结果 - union 属性没有 KVO 观察者事件。
【问题讨论】:
-
或者更好的是,明确说明您对值的更改(
willChangeValueForKey:,didChangeValueForKey:); -
内存布局不应该对 assignment/KVO 机制起作用。即使联合的值不正确,也应该调用观察者。当覆盖
valueForKey:并从联合字节返回手动生成的NSValue时,通过willChangeValueForKey:和didChangeValueForKey:手动发出更改有效。但是,这不是问题的主题。 -
它不适用于“observeValueForKeyPath:”,但可以使用“didChangeValueForKey:”。奇怪。
-
在我的实际应用中,当没有覆盖
valueForKey:并返回手动构造的NSValue对象时,didChangeValueForKey:出现异常。 -
哇,真正的 SSCCE!我还没有在狗的年龄见过周围的人。我看到了同样的结果;这是一个有趣的发现。
标签: objective-c key-value-observing unions