2

我有一个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:了响应的调用NSManagedObjectContextDidSaveNotificationbgContext但是到了调用的时候,已经进行了更改并且已经触发了 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];
        }
    }
}

这有效,但感觉不是最佳的。您对最佳实践有更好的建议或参考吗?

4

1 回答 1

0

是否可以使用 NSManagedObjectContextDidSaveNotification 来触发 UI 更新而不使用 KVO?

于 2012-10-06T20:31:31.187 回答