3

メンバー クラスと 1 対多の関係を持つ 1 つのマネージド オブジェクトがあります。メンバーのオブザーバーを追加すると、うまくいきました。リレーションシップに 1 つの新しいメンバーが追加されると、observeValueForKeyPath が新しいオブジェクトで呼び出され、変更ディクショナリに新しいメンバー オブジェクトが含まれます。ただし、observeValueForKeyPath は、すべての値が nil で 2 回目のトリガーとなり、ディクショナリを new="NULL" に変更します。2つ目のトリガーは?ブレークポイントを設定しましたが、誰がトリガーしたかわかりません。

@interface FooObject : NSManagedObject {}
@property (nonatomic, strong) NSString *fooId;
@property (nonatomic, strong) NSSet* members;
@end

@implementation FooObject
@dynamic fooId;
@dynamic members;

- (NSMutableSet*)membersSet {
    [self willAccessValueForKey:@"members"];

    NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"members"];

    [self didAccessValueForKey:@"members"];
    return result;
}

- (void)registerObservers {
    [self addObserver:self
           forKeyPath:@"members"
              options:NSKeyValueObservingOptionNew
              context:nil];
}

- (void)unregisterObservers {
    @try{
        [self removeObserver:self forKeyPath:@"members"];
    }@catch(id anException){
        //do nothing, obviously it wasn't attached because an exception was thrown
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
    id valueNewSet = [change objectForKey:NSKeyValueChangeNewKey];
    if (![valueNewSet isKindOfClass:[NSSet class]]) {
            // not a NSSet, it contains <null> value
            NSLog(@"%@", change);
            NSLog(@"%@", object);
    }
    if ([[change objectForKey:NSKeyValueChangeKindKey] intValue] == NSKeyValueChangeInsertion) {
           // insert change is valid, process the changes
    }

}
@end

ログ出力:

{
    kind = 1;
    new = "<null>";
}

<FooObject: 0xfa9cc60> (entity: FooObject; id: 0xfa9be00 <x-coredata://39DB31FD-6795-4FDE-B700-819AB22E5170/SHInterest/p6> ; data: {
    fooId = nil;
    members = nil;
})

EDIT 1 NSLog(@"%@", change); にブレークポイントを設定しました。これはスタック トレースですが、誰がこの呼び出しを行ったのかを特定するのにはあまり役に立ちません。

メイン -> UIApplicationMain -> NSKeyValueNotifyObserver -> observeValueForKeyPath:ofObject:change:context

EDIT 2 多分これはまだバグですか? http://www.cocoabuilder.com/archive/cocoa/182567-kvo-observevalueforkeypath-not-reflecting-changes.html

4

1 に答える 1

0

「暗黙の」割り当て (したがって、KVO オブザーバーの通知) が明らかに MO の割り当て解除の一部としてのみ発生するという同じ問題に遭遇しています。その後、関連する MO の割り当てを解除する過程で一時的に 1 対多の関係が設定されると思いNSNullます (削除ルールのカスケードが適用される場合)。

次に、挿入と削除の種類を変更するために、私の KVO オブザーバーも受け入れNSKeyValueChangeSettingてアサートしchange[NSKeyValueChangeNewKey] == NSNull.nullます。それを実用的な解決策と呼んでください。

于 2015-02-10T10:10:52.973 に答える