我有一个NSManagedObject
子类,它具有一对多关系和一个在数据模型中设置的获取属性,以提供该关系中对象的过滤子集。
//School.h
@interface School : NSManagedObject
@property (nonatomic, retain) NSSet *pupils;
@property (nonatomic, retain) NSArray *starPupuils;
@end
//School.m
@implementation School
@dynamic pupils;
@dynamic starPupils;
@end
然后我有一个视图控制器,它监视 School 对象以了解学生的变化,然后刷新 starPupils 数据:
-(void)setSchool:(School *)school
{
…
self.contentArray = [self.school starPupils];
[self.school addObserver:self
forKeyPath:@"pupils"
options:nil
context:nil];
…
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"pupils"])
{
self.contentArray = [self.school starPupils];
}
}
这在首次访问获取的属性时工作正常,但正如预期的那样,starPupils 数组被缓存并且不会在添加和删除学生时自行更新。
如果目标实体中的对象发生更改,您必须重新评估获取的属性以确保它是最新的。您用于
refreshObject:mergeChanges:
手动刷新属性——这会导致在下次触发对象故障时再次执行与此属性关联的获取请求。—核心数据编程指南:关系和获取的属性
我的问题是,我应该refreshObject:mergeChanges:
从哪里打电话?
我已经研究过从处理添加和删除学生的代码库部分调用它,并且在相同的上下文中工作正常,但通常更改发生在单独的背景上下文中。
这个背景上下文parentContext
设置为mainContext
我的视图控制器总是处理的,所以当它被保存时,更改会自动合并回mainContext
. 我调查refreshObject:mergeChanges:
了响应的调用NSManagedObjectContextDidSaveNotification
,bgContext
但是到了调用的时候,已经进行了更改并且已经触发了 KVO 的东西。
我尝试添加以下内容,但最终陷入无限循环:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"pupils"])
{
[self.school.managedObjectContext refreshObject:self.school mergeChanges:YES];
self.contentArray = [self.school starPupils];
}
}
我目前的实现如下:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"pupils"])
{
if (self.contentArray == [self.school starPupils])
{
/*
self.contentArray is currently pointing at previous fetched starPupils
we need to reset the object to a faulted state
this will twigger another KVO notification for @"pupils" but the code within this if statement will not be executed again
*/
[self.school.managedObjectContext refreshObject:self.school mergeChanges:YES];
self.contentArray = [self.school starPupils];
}
}
}
这有效,但感觉不是最佳的。您对最佳实践有更好的建议或参考吗?