Cocoa 刷新NSManagedObject的获取属性
我有一个Cocoa 刷新NSManagedObject的获取属性,cocoa,core-data,nsmanagedobjectcontext,Cocoa,Core Data,Nsmanagedobjectcontext,我有一个NSManagedObject子类,它具有一对多关系和一个在数据模型中设置的获取属性,以提供该关系中对象的过滤子集 //School.h @interface School : NSManagedObject @property (nonatomic, retain) NSSet *pupils; @property (nonatomic, retain) NSArray *starPupuils; @end //School.m @implementation School @dyn
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
然后我有一个视图控制器,它监视学校对象对学生的更改,然后刷新StarStudios数据:
-(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];
}
}
当第一次访问获取的属性时,这可以正常工作,但正如预期的那样,starproducts数组被缓存,并且不会在添加和删除学生时更新自身
如果目标实体中的对象发生更改,则必须重新评估获取的属性,以确保它是最新的。您可以使用refreshObject:mergeChanges:
手动刷新属性,这将导致在下次触发对象错误时再次执行与此属性关联的提取请求。-
我的问题是,我应该在哪里调用refreshObject:mergeChanges:
from?
我已经研究过从代码库中处理添加和删除学生的部分调用它,并且在相同的上下文中可以很好地工作,但更改通常发生在单独的背景上下文中
此后台上下文将其parentContext
设置为my view controller始终处理的mainContext
,因此保存时,更改会自动合并回mainContext
。我研究了调用refreshObject:mergeChanges:
以响应bgContext
的NSManagedObjectContextDidSaveNotification
,但在调用时,更改已经完成,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];
}
}
}
这是有效的,但感觉不是最佳的。您对最佳实践有什么更好的建议或参考吗?是否可以使用NSManagedObjectContextDidSaveNotification触发UI更新而完全不使用KVO?是否可以使用NSManagedObjectContextDidSaveNotification触发UI更新而完全不使用KVO?上下文保存得很好但是,无论数据发生了什么变化,都会定期调用该通知。使用KVO意味着我只能在特定相关数据发生更改时触发此更新。NSManagedObjectContextObjectsIDChangeNotification而不是NSManagedObjectContextDidSaveNotification可能会起作用?感谢您的建议。NSManagedObjectContextObjectsIDChangeNotification也会定期被调用,而确定它是否是相关的更改实际上就是复制KVO免费提供给我的功能(只有当该对象更改时,我才会收到通知,而不是当任何其他对象也更改时)…我想也许上面列出的当前解决方案是我必须坚持的。还值得指出的是,在无限循环中,当我刷新对象时,KVO会再次触发,也适用于更改通知…我为避免该循环而进行的检查仍然是必需的NSManagedObjectContextObjectsIDChangeNotification与NSManagedObject上的ChangedValuesRecurrentEvent和更新属性结合使用时功能非常强大。多年来,我一直使用KVO进行CoreData UI绑定,但我已迁移到通知,因为批处理很方便,而且它可以更好地处理已删除的托管对象。不过,上下文会定期保存,无论数据发生了什么变化,都会调用该通知。使用KVO意味着我只能在特定相关数据发生更改时触发此更新。NSManagedObjectContextObjectsIDChangeNotification而不是NSManagedObjectContextDidSaveNotification可能会起作用?感谢您的建议。NSManagedObjectContextObjectsIDChangeNotification也会定期被调用,而确定它是否是相关的更改实际上就是复制KVO免费提供给我的功能(只有当该对象更改时,我才会收到通知,而不是当任何其他对象也更改时)…我想也许上面列出的当前解决方案是我必须坚持的。还值得指出的是,在无限循环中,当我刷新对象时,KVO会再次触发,也适用于更改通知…我为避免该循环而进行的检查仍然是必需的NSManagedObjectContextObjectsIDChangeNotification与NSManagedObject上的ChangedValuesRecurrentEvent和更新属性结合使用时功能非常强大。多年来,我一直使用KVO进行CoreData UI绑定,但我已经迁移到了通知,因为批处理很方便,而且它可以更好地处理已删除的托管对象。