在更新时跟踪NSManagedObject属性并立即更新视图

时间:2014-09-05 15:43:37

标签: ios core-data nsmanagedobject key-value-observing magicalrecord

我有一个问题,我该如何收听数据模型中的更改。

我有NSManagedObject电子邮件,其中包含属性进度。因此,当应用程序发送电子邮件时,我每次都会更新属性进度。

我想听数据模型,如果更改,请更新我的视图。

我补充说:

 for (SAPEmail *email in _emails)
    {
        [self addObserver:email forKeyPath:@"progress" options:NSKeyValueObservingOptionNew context:NULL];
    }


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"progress"])
    {
        SAPEmail *email = object;

        NSLog(@">>>>>>>>>>> progress: %@", email.progress);
    }
}

但似乎它对我不起作用。

我也使用MagicalRecord。

我也试着观察上下文

[[NSNotificationCenter defaultCenter] 
      addObserver:self 
         selector:@selector(handleDataModelChange:) 
             name:NSManagedObjectContextObjectsDidChangeNotification 
           object:myManagedObjectContext];

但是当我调试我的数据模型已经更新了10次(因为我从0 - 9更新进度),但handleDataModelChange在所有更新之后只调用了一次。但是每次更新数据模型以更新进度视图时,我都需要获得全部10次更新。

如果我使用这个

,还有一个
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:nil]; 

然后例如尝试刷新数据:

- (void)managedObjectContextDidSave:(NSNotification *)notification
{
    NSLog(@">>>>>>>>>+++++");

    _emails = [SAPCoreDataEmailHelper emailsWithStatus:EmailStatusInProgress];

    [_theTableView reloadData];
}

+ (NSArray *)emailsWithStatus:(EmailStatus)status
{
    NSPredicate *prediacte = [NSPredicate predicateWithFormat:@"status == %d", status];
    NSArray *emails = [SAPEmail MR_findAllWithPredicate:prediacte];
    return emails;
}

我可以看到NSLog是如何工作的,但我的应用程序是冻结的。

2 个答案:

答案 0 :(得分:1)

更好的是,将获取的对象保存在NSFetchedResultsController中。通过这种方式,您可以自动监视非常具体的实体,而无需过多详细地观察每个属性。

您是否有控制器实施NSFetchedResultsControllerDelegate方法。这非常简单,使用核心数据检查Xcode模板(例如,Master-Detail Project,检查" Core Data")。

答案 1 :(得分:0)

您正在错误地设置观察者,请使用以下代码设置您的观察结果。

 for (SAPEmail *email in _emails)
 {
     [email addObserver:self forKeyPath:@"progress" options:NSKeyValueObservingOptionNew context:NULL];
 }

我还建议setting the context parameter正确触发KVO观察。


更新

如果您想观察核心数据的变化,您可以选择一些选项。我认为你并没有意识到有多种方法可以做到这一点。第一种方法是监视单个对象上单个属性的更改。这是KVO方法。如果要监听特定上下文的保存事件,则需要使用NSNotificationCenter方法。当您对多个上下文进行更改时,您需要将两者混合使用。也就是说,如果您正在观察上下文A中对象的属性,并且您在上下文B中对该对象/属性进行了更改,则需要在NSManagedObjectContextDidSaveNotification上设置NSNotificationCenter观察处理程序,以将来自上下文B的新更改合并到上下文A.从那里,当上下文合并完成后,然后触发对上下文A中的属性/对象的KVO观察。

在您的情况下,在managedOjbectContextDidSave:方法中,您需要致电 -mergeChangesFromContextDidSaveNotification:在上下文之间合并您的更改。我还建议使用多个上下文,而不是在SAPCoreDataEmailHelper类中保存单个上下文。当您进入多线程场景时,您将遇到具有单个上下文和多个线程的随机崩溃。