9

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

我有一个“仓库”实体,它有两个对多关系“人员”和“卡车”。我想观察在给定“仓库”对象的情况下,其中一个关系(并了解其中一个关系)何时发生变化(插入、删除)。

目前我正在这样做:

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

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

但是每次两个相关集合之一发生变化时,observeValueForKeyPath都会被调用两次(每个键路径一次)。

我做错了吗?查看“更改”字典,(也观察 OptionOld)显示没有意外更改(当我更换人员时,卡车没有更改),但通知仍然出现。

谢谢,彼得罗

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

编辑2:即使是简单的属性,它也会与 managedctx 保存操作有关吗?好像当您保存时,整个对象都被认为已更改..

4

5 回答 5

10

在 Key Value Observing Programming Guide 中说

如果您使用 Core Data,您可以将父级注册到应用程序的通知中心,作为其托管对象上下文的观察者。父级应该以类似于键值观察的方式响应子级发布的相关更改通知。

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

于 2013-03-27T22:32:58.650 回答
3

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

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

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

于 2013-03-27T15:57:19.220 回答
1

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

但我可以肯定的是,第一次调用它的原因是你做了类似的事情[Depot addPerson:person],而第二次调用它的原因是 MOC 保存操作将发布一个NSManagedObjectContextDidSaveNotification通知,让你的观察者认为另一个修改刚刚发生.

而我的问题更糟糕的是,因为观察者,我会丢失一些我对核心数据的修改。

这让我觉得我这两天都傻了。

我正在考虑NSManagedObjectContextDidSaveNotification在@Mundi 的回答中使用 register

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

于 2013-05-17T15:00:51.797 回答
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;
}
于 2014-01-08T15:29:53.030 回答
0

如果您想知道何时从 to-many trucks 关系中添加或删除项目,则需要对计数(在您的视图控制器中的某处)执行 KVO,如下所示:

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

于 2018-08-02T14:10:01.040 回答