Objective-C KVO不适用于C联合 [英] Objective-C KVO doesn't work with C unions

查看:118
本文介绍了Objective-C KVO不适用于C联合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用KVO在Objective-C类上观察联合类型的属性,但是似乎我对此并不走运.我做了一些实验:只要我使用C结构,一切都可以正常工作.一旦我用联合替换了该结构,自动KVO就不再起作用(不再调用observeValueForKeyPath).

I need to observe union-typed properties on an Objective-C class using KVO, but it seems I have no luck with this. I did some experiments: everything works fine as long as I am using a C struct. As soon as I replace the struct with a union, automatic KVO doesn't work anymore (observeValueForKeyPath is not being called).

这是我的小班考试:

AppDelegate.h:

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:

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实现中的错误或缺失功能?

Am I doing something wrong or is this a bug or missing feature in the Objective-C runtime/KVO implementation?

注意:我知道我可以通过重写属性设置器来手动实现此功能,但这不是此问题的重点.答案应该让我知道为什么在这种情况下自动KVO无法正常工作.

Note: I know I can implement this manually, by overriding the property setter, but this is not the point of this question. The answer should give me an idea of why the automatic KVO doesn't work in this case.

更新:明确起见,这是一个简单的测试用例,将struct属性的KVO观察者与union属性的KVO观察者进行了比较.这些属性是不相关的.它们具有独立的ivar,具有独立的内存后备存储.您可以删除struct属性并运行测试,结果仍然相同– union属性没有KVO观察者事件.

Update: Just to make this clear, this is a simple test case comparing the KVO observer on a struct property to that on a union property. These properties are not interrelated. They have independent ivars with independent memory backing stores. You can remove the struct property and run the test, still the same result – no KVO observer event for the union property.

推荐答案

属性与OP的问题无关.

我在发烧引起的幻觉中误读了这一点.

The properties aren't related in OP's question.

I misread that in a fever induced hallucination.

联盟只是被KVO/KVC破坏了.将其留在下面,因为它仍然很有趣.

Unions are just flat out busted in KVO/KVC. Leaving the text below because it is still interesting.

KVO不能通过观看内存或播放此类棘手的恶作剧来工作.它的工作原理是动态动态创建子类,覆盖setter方法,并在调用setter时自动调用willChange.../didChange...方法.

KVO doesn't work by watching memory or playing any such tricky shenanigans like that. It works by dynamically creating a subclass on the fly, overriding the setter method, and invoking the willChange.../didChange... methods automatically when the setter is called.

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

Thus, you effectively have 2 properties with 1 backing store. As far as KVO is concerned, though, they are in total isolation from each other.

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

What you want is dependent keys. You can use +keyPathsForValuesAffectingValueForKey: to create a dependency between the two keys such that calling either setter will trigger a change for the other property.

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

I don't know if it supports co-dependnence; if it supports what would effectively be a circular dependency.

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

Alternatively, you ought to be able to override the setter to call willChange/didChange for the other property (as well as the property being changed).

如果您要willChange/didChange都为两个键触发,而任一属性均发生更改,则将使用相关的键. IE.如果您对结构感到不满,则该联合会有效地发生变化,并且该联合属性的观察者应会看到会更改设置结构版本的意愿/意愿改变.

The related keys would be used if you want willChange/didChange to fire for both keys if either property changes. I.e. if you muck with the struct, the union effectively changes and observers of the union property should see a will/did change in response to setting the struct version.

我刚刚测试了它.你是对的.工会有些奇怪.它断了.以上所有内容仍然适用,但没有好处.

I just tested it. You're right. Something is odd with unions. It is flat out broken. All of the above still remains true, but it does no good.

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

Radar filed: rdar://problem/13003794

哦,整洁.带工会的KVO根本行不通.看来,运行时甚至根本无法识别该类具有一个名为vectorUnionValue的键.

Oooh... neat. KVO w/unions simply doesn't work. It appears that the runtime simply does not even recognize that the class has a key called vectorUnionValue at all.

我添加了:

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

+ (NSSet *)keyPathsForValuesAffectingVectorUnionValue
{
    return [NSSet setWithObject:@"vectorStructValue"];
}

哪个引起了运行时异常:

Which caused a runtime exception:

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.'

这篇关于Objective-C KVO不适用于C联合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆