6

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が機能しない理由を私に教えてくれるはずです。

更新:これを明確にするために、これはstructプロパティのKVOオブザーバーをunionプロパティのKVOオブザーバーと比較する単純なテストケースです。これらのプロパティは相互に関連していません。それらには、独立したメモリバッキングストアを備えた独立したivarがあります。structプロパティを削除してテストを実行できますが、それでも同じ結果になります。unionプロパティのKVOオブザーバーイベントはありません。

4

1 に答える 1

10

OPの質問では、プロパティは関連していません。

私はそれを熱で誘発された幻覚と読み違えました。

労働組合は、KVO/KVC で一網打尽にされています。まだ興味深いので、以下のテキストを残します。


KVO は、記憶を見たり、そのようなトリッキーな悪ふざけをしたりしても機能しません。その場でサブクラスを動的に作成し、setter メソッドをオーバーライドし、willChange.../didChange...setter が呼び出されたときにメソッドを自動的に呼び出すことによって機能します。

したがって、実質的に 1 つのバッキング ストアを持つ2プロパティがあります。ただし、KVOに関する限り、それらは互いに完全に分離されています。

必要なのは依存キーです。を使用+keyPathsForValuesAffectingValueForKey:して、2 つのキー間の依存関係を作成し、いずれかのセッターを呼び出すと他のプロパティの変更がトリガーされるようにすることができます。

共依存をサポートしているかどうかはわかりません。事実上循環依存となるものをサポートする場合。

または、セッターをオーバーライドしwillChange/didChangeて、他のプロパティ (および変更されるプロパティ) を呼び出すことができる必要があります。


いずれかのプロパティが変更された場合に両方のキーwillChange/didChangeを起動する場合は、関連するキーが使用されます。つまり、構造体をいじると、共用体が効果的に変更され、共用体プロパティのオブザーバーは、構造体バージョンの設定に応じて will/did の変更を確認する必要があります。

私はちょうどそれをテストしました。あなたが正しい。労働組合の何かがおかしい。それは完全に壊れています。上記のすべては依然として当てはまりますが、それは役に立ちません。

レーダー提出: rdar://problem/13003794


うーん...すっきり。KVO w/unions は単純に機能しません。ランタイムは、クラスに呼び出されたキーがあることさえまったく認識していないよう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.'
于 2013-01-12T18:38:09.040 に答える