Objective-C KVO不适用于C联合会

sta*_*ugs 6 objective-c key-value-observing unions

我需要在使用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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

输出:

2013-01-12 17:38:26.447 KVOTest[57522:303] keyPath vectorStructValue did change, object: <AppDelegate: 0x100614200>
Run Code Online (Sandbox Code Playgroud)

我做错了什么,或者这是Objective-C运行时/ KVO实现中的错误或遗漏功能?

注意:我知道我可以通过覆盖属性setter手动实现它,但这不是这个问题的重点.答案应该让我知道为什么自动KVO在这种情况下不起作用.

更新:为了清楚说明,这是一个简单的测试用例,它将struct属性上的KVO观察者与union属性上的KVO观察者进行比较.这些属性不相互关联.他们有独立的ivars和独立的内存支持商店.您可以删除struct属性并运行测试,结果仍然相同 - union属性没有KVO观察者事件.

bbu*_*bum 10

这些属性与OP的问题无关.

我误解了发烧引起的幻觉.

工会在KVO/KVC中被淘汰出局.留下下面的文字,因为它仍然很有趣.


KVO无法通过观察记忆或玩任何像这样棘手的恶作剧来工作.它的工作原理是动态创建一个子类,覆盖setter方法,并在调用willChange.../didChange...setter时自动调用方法.

因此,您实际上有2个属性1个后备存储.然而,就KVO而言,它们完全相互隔离.

你想要的是依赖键.您可以使用+keyPathsForValuesAffectingValueForKey:在两个键之间创建依赖关系,以便调用setter将触发另一个属性的更改.

我不知道它是否支持共同依赖; 如果它支持有效的循环依赖.

或者,您应该能够覆盖setter以调用willChange/didChange其他属性(以及要更改的属性).


如果你想在相关的密钥将用来willChange/didChange射击的两个键,如果任一属性的变化.即如果你搞砸了结构,那么union会有效地改变,union属性的观察者应该看到一个意愿/做了改变以响应设置结构版本.

我刚试过它.你是对的.工会有点奇怪.它破碎了.所有这些仍然是正确的,但它没有好处.

雷达提交:rdar:// problem/13003794


哦......整洁.KVO w /工会根本不起作用.似乎运行时甚至不会识别该类具有完全被调用的键vectorUnionValue.

我补充说:

+ (NSSet *)keyPathsForValuesAffectingVectorStructValue
{
    return [NSSet setWithObject:@"vectorUnionValue"];
}

+ (NSSet *)keyPathsForValuesAffectingVectorUnionValue
{
    return [NSSet setWithObject:@"vectorStructValue"];
}
Run Code Online (Sandbox Code Playgroud)

这导致了运行时异常:

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.'
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这是正确的.为什么只有一个支持商店?实际上你可以删除struct属性,这只是为了澄清我的例子.它没有改变任何关于自动KVO实现不适用于union属性的事实.至于willChange/didChange实现:我知道我可以手动完成,问题是为什么它不能自动工作(应该如此)? (2认同)