メンバー クラスと 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