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

标签 objective-c key-value-observing unions

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

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

更新:为了清楚起见,这是一个简单的测试用例,比较结构属性上的 KVO 观察器和联合属性上的观察器。这些属性不相关。他们有独立的ivars和独立的内存后备存储。您可以删除 struct 属性并运行测试,结果仍然相同——联合属性没有 KVO 观察器事件。

最佳答案

属性与 OP 的问题无关。

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

工会在 KVO/KVC 中遭到彻底破坏。留下下面的文字,因为它仍然很有趣。


KVO 无法通过观察内存或玩任何此类棘手的恶作剧来工作。它的工作原理是动态创建子类,重写 setter 方法,并在调用 setter 时自动调用 willChange.../didChange... 方法。

因此,您实际上拥有 2 个属性1 个后备 存储。不过,就 KVO 而言,它们彼此完全隔离。

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

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

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


如果您希望 willChange/didChange任一属性更改 时为两个 键触发,则将使用相关键。 IE。如果你弄乱了结构,联合会有效地改变,并且联合属性的观察者应该看到一个 will/did 改变以响应设置结构版本。

我刚测试过。你是对的。工会有些奇怪。它完全坏了。以上所有内容仍然成立,但没有任何好处。

雷达归档:rdar://problem/13003794


哦...整洁。带工会的 KVO 根本行不通。运行时似乎根本没有识别出该类有一个名为 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.'

关于Objective-C KVO 不适用于 C 联合体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14295505/

相关文章:

objective-c - setNeedsDisplay 不起作用?

ios - KVO 核心数据和原始访问器

通过 typedef 定义 C++ 新类型

iphone - 当 tableview 比屏幕长时将其转换为图像

ios - 他们有什么方法可以识别用户更新应用程序和用户第一次在 iOS 中安装应用程序吗?

ios - 在 KVO 中使用嵌套键路径

c++ - 为 64 位和 32 位构建创建指针大小的 union

c++ - C++ Cast的实现

iphone - 扩展多行 UILabel

objective-c - Clang 静态分析器对自动释放发出警告