2013-03-27 37 views
9

大家好多年读书的StackOverflow,现在我决定加入。我竭力让这个解决:志愿的addObserver到CoreData对象的一个​​一对多的关系

我有两个一对多的关系,“人”和“卡车”一个“仓库”的实体。我想观察何时,给定一个“仓库”对象时,在其中一个关系中存在变化(插入,移除)(并理解其中哪一个)。

目前,我这样做:在两个相关的收藏品之一

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

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

,但每次有新的变化,observeValueForKeyPath被调用两次(一次为每的keyPath)。

难道我做错了?看着“改变”字样(用OptionOld观察)显示没有意外的变化(当我改变人物时,卡车没有改变),但通知仍然提出。

谢谢,彼得

编辑:看来,这两个时代的“变革”字典包含在“新”领域的整个关系。 (显然,一个人的时间和一次卡车)

EDIT2:因为它发生甚至bserving简单的属性,难道是managedctx保存操作有关?就好像当你保存,整个对象被认为是改变..

回答

3

如果设置卡车原子(something.trucks = newArray),你会得到一个值定通知。请使用由[ something mutableArrayValueForKey:@"trucks" ]返回的可变数组使用addObject/removeObject。

您还可以使用/实现国际志愿者组织生成的访问insertObjectIntoTrucks:/countOfTrucks

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

+1

+1同意。考虑修改现有的值集合,而不是用不同的集合替换整个集合。 – Caleb 2013-03-27 16:00:25

+0

谢谢,是的,但是Depot是一个CoreData NSManagedObject子类,因此应该已经实现了KVO兼容访问器。我正在做你说的,事实上,我只是在关系中增加一个新的卡车实体,从不替换/设置整个集合(关系)。这就是为什么我不明白。仿佛我看到了两个keypaths例如“卡车”和“sqmeters”(这不是一个关系),如果“sqmeters”被修改,两个通知被触发(也一为“卡车” kpath) – Peterdeka 2013-03-27 16:19:39

+0

关键路径可以依靠彼此......也许这就是发生了什么?否则,你将不得不在其他地方 – nielsbot 2013-03-27 16:24:26

9

在Key值观察编程指南它说,

如果你使用的核心数据,您可以注册应用程序的通知中心,其管理的对象上下文的观察者父。家长应以类似于键值观察的方式来回应孩子发布的相关变化通知。

这能有效地意味着,推荐的做法是不要使用addObserver:forKeyPath:options:context:,但报名参加NSManagedObjectContextDidSaveNotification代替。

+0

是的,这是我的第二选择,因为我只想观察一个对象(但可以在后台修改多个对象),我认为这是对通知的浪费,因为我得到了所有更改的通知对象并且必须过滤掉通知 – Peterdeka 2013-03-28 23:28:36

+1

@Peterdeka这仍然是最好和最正确的答案。你应该接受它。 – Mundi 2013-06-04 14:34:57

1

我带着同样的问题。而且我仍然坚持这个问题。

但我敢肯定的是,第一次被叫的原因是你做了类似[Depot addPerson:person]的事情,而第二次被叫的原因是MOC保存动作将发布NSManagedObjectContextDidSaveNotification通知,让你的观察者认为另一种修改恰好发生。

而我的问题更糟的是,由于观察者的原因,我将丢失一些核心数据的修改。

这让我觉得我近两天很愚蠢。

我想用在@Mundi的回答登记NSManagedObjectContextDidSaveNotification

如果任何人有一个更好的办法,请让我知道尽快

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; 
}