【问题标题】:Track NSManagedObject property when it was updated and immediately update view在更新时跟踪 NSManagedObject 属性并立即更新视图
【发布时间】:2014-09-05 15:43:37
【问题描述】:

我有一个问题,我如何才能听到我的数据模型的变化。

我有带有属性进度的 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 是如何工作的,但是我的应用程序被冻结了。

【问题讨论】:

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


    【解决方案1】:

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

    您的控制器是否实现了NSFetchedResultsControllerDelegate 方法。这真的很简单,使用 Core Data 查看 Xcode 模板(例如 Master-Detail Project,查看“Core Data”)。

    【讨论】:

      【解决方案2】:

      您设置的观察者不正确,请使用以下代码设置您的观察。

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

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


      更新

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

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

      【讨论】:

      • 感谢您每次都回答您帮助我)我有单身人士为我发送电子邮件,在这里我使用神奇的导入来设置所有属性以及进度。在视图控制器的另一个对象中,我想观察我所有的电子邮件,当我初始化这个视图控制器时,我创建了 SAPEmail MR_findAllWithPredicate。但我认为当核心数据发生变化时,我在视图控制器中使用的电子邮件并不知道它。因为更改发生在上下文中,而不是我通过 MR_findAllWithPredicate 获得的对象。对吗?
      • 还是观察不到
      猜你喜欢
      • 2012-03-07
      • 2018-05-23
      • 2015-02-15
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多