检测对单个 coredata 实体的更改
Posted
技术标签:
【中文标题】检测对单个 coredata 实体的更改【英文标题】:Detect changes to single coredata entity 【发布时间】:2016-11-02 00:46:31 【问题描述】:我有以下核心数据实体:
@interface Car (CoreDataProperties)
@property (nullable, nonatomic, retain) NSSet<Part *> *parts;
@end
@interface Part (CoreDataProperties)
@property (nullable, nonatomic, retain) Car *car;
@end
这是汽车和零件之间的一对多关系。在我的一个视图控制器中,我显示了一个包含所有部件的汽车视图。我想听听汽车零件的变化。
我认为使用 KVO 会很容易。
- (void) viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
[self.car addObserver:self forKeyPath:@"parts" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
然后:
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
if ([@"parts" isEqualToString:keyPath])
// do what I need to do with new parts
但是,当我从服务器拉取更改以更新汽车零件时,即使我没有更改任何零件,也会收到对 observeValueForKeyPath 方法的意外回调。
想知道故障是否是问题所在: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/FaultingandUniquing.html#//apple_ref/doc/uid/TP40001075-CH18-SW7
希望使用 KVO,但也许使用 coredata 对象并不是一个好主意。我做错了什么还是应该使用替代方法?
如果我不应该使用 KVO,我相信我的其他选择是: 1. 监听 MOC 变化。这不是很好,因为我真的不知道对象发生了什么变化。 2. 在带有谓词的部件上实现 FetchedResultsController 以仅查找我感兴趣的汽车。看起来有点矫枉过正,但我认为这将满足我的需求。
【问题讨论】:
【参考方案1】:NSFetchedResultsController
是观察某些数据子集变化的首选方式。
对于单个对象,您可以观察到 NSManagedObjectContext
的变化。
订阅NSManagedObjectContextObjectsDidChangeNotification
:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(contextDidChange:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:context];
当通知到达时,处理它的userInfo
:
- (void)contextDidChange:(NSNotification *)notification
NSManagedObjectContext *context = notification.object;
NSDictionary *userInfo = notification.userInfo;
NSArray *invalidatedAll = userInfo[NSInvalidatedAllObjectsKey];
NSSet *invalidated = userInfo[NSInvalidatedObjectsKey];
NSSet *deleted = userInfo[NSDeletedObjectsKey];
NSSet *updated = userInfo[NSUpdatedObjectsKey];
NSSet *refreshed = userInfo[NSRefreshedObjectsKey];
// context reset
if (invalidatedAll)
// probably you better have to dismiss your VC here.
return;
// invalidated
if ([invalidated containsObject:self.car])
// it make sense to dismiss here too.
return;
// deleted
if ([deleted containsObject:self.car])
// and here.
return;
// refreshed
if ([refreshed containsObject:self.car])
// update your interface.
return;
// updated
if ([updated containsObject:self.car])
// update your interface.
return;
要在相关Parts
更新时接收有关Car
对象的通知,请参阅此answer。
您可以从changedValues 属性中获取更改的属性列表。
别忘了退订:
- (void)dealloc
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:NSManagedObjectContextObjectsDidChangeNotification
object:context];
更新:
这是作为UIViewController
类别实现的概念:BTDependentVC
【讨论】:
以上是关于检测对单个 coredata 实体的更改的主要内容,如果未能解决你的问题,请参考以下文章
如何参考CoreData中同一实体的单个属性更新实体的属性?