KVO addObserver与Core Data对象的一对多关系

时间:2013-03-27 12:14:04

标签: ios objective-c core-data key-value-observing

大家好几年读StackOverflow,现在我决定加入。我正在努力解决这个问题:

我有一个“Depot”实体,它有两对多的关系“Persons”和“Trucks”。我想观察一下,给定一个“Depot”对象,其中一个关系中有变化(插入,删除)(并理解其中一个)。

目前我这样做:

[mydepot addObserver:self forKeyPath:@"Trucks" options:NSKeyValueObservingOptionNew context:nil];

[mydepot addObserver:self forKeyPath:@"Persons" options:NSKeyValueObservingOptionNew context:nil];

但是每当两个相关集合中的某个集合发生变化时,observeValueForKeyPath会被调用两次(每个密钥路径一次)。

我做错了吗?查看“更改”字典,(与OptionOld一起观察)显示没有意外的变化(当我改变人员时,卡车没有改变),但仍然提出通知。

谢谢,Pietro

编辑:似乎两次“更改”字典都包含“新”字段中的整个关系。 (显然有一次人和一次卡车)

edit2:即使保留简单的属性,它是否与managedctx保存操作有关?好像在保存时,整个对象被认为已经改变了..

5 个答案:

答案 0 :(得分:9)

在Key Value Observing Programming Guide中,它说

  

如果您正在使用Core Data,则可以将应用程序通知中心的父级注册为其托管对象上下文的观察者。家长应以类似于键值观察的方式回应孩子们发布的相关变更通知。

这实际上可能意味着建议的做法不是使用addObserver:forKeyPath:options:context:,而是注册NSManagedObjectContextDidSaveNotification

答案 1 :(得分:3)

如果您以原子方式设置卡车(something.trucks = newArray),您将获得一个值设置通知。而是在[ something mutableArrayValueForKey:@"trucks" ]返回的可变数组上使用addObject / removeObject。

您还可以使用/实施KVO生成的访问者insertObjectIntoTrucks: / countOfTrucks等。

您应该阅读KVO文档。在“索引多对多关系合规性”和“无序关系合规性”here下。

答案 2 :(得分:1)

我遇到了同样的问题。我仍然坚持这个问题。

但我确定第一次被调用的原因是你做[Depot addPerson:person]之类的事情,而第二次被调用的原因是MOC保存动作会发布NSManagedObjectContextDidSaveNotification 1}}通知,让你的观察者认为另一种修改只会发生。

在我的问题中更糟糕的是,由于观察者的缘故,我将丢失一些核心数据的修改。

这让我觉得我差不多两天都这么傻。

我想在@Mundi的回答中使用注册NSManagedObjectContextDidSaveNotification

如果有人有更好的方法,请尽快告诉我

答案 3 :(得分:0)

我将一些缓存作为NSManagedObject的属性保留,并且需要使这些缓存无效。我首先考虑使用KVO并听取NSManagedObjectContextDidSaveNotification

对我来说最简单的解决方案就是像这样实现方法– [NSManagedObject didSave]– [NSManagedObject didTurnIntoFault]

@interface BazClass ()
@property (nonatomic, strong) NSArray* sortedItems;    // sorted items cache
@end

@implementation BazClass

@dynamic items; // this is a to many relationship. i.e. NSOrderedSet
@synthesize sortedItems;

- (NSArray*)sortedItems
{
    if (!_sortedItems) {
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"foo" ascending:YES];
        _sortedItems = [self.items sortedArrayUsingDescriptors:@[sortDescriptor]];
    }
    return _sortedItems;
}

// didSave and didTurnIntoFault will delete the sorted items cache
- (void) didSave
{
    self.sortedItems = nil;
}

-(void) didTurnIntoFault
{
    self. sortedItems = nil;
}

答案 4 :(得分:0)

如果您想知道何时在多对卡车关系中添加或删除项目,则需要对计数(在视图控制器中的某个位置)执行KVO,如下所示:

[self.depot addObserver:self forKeyPath:@"trucks.@count" options:0 context:nil];