在更新时跟踪 NSManagedObject 属性并立即更新视图
Posted
技术标签:
【中文标题】在更新时跟踪 NSManagedObject 属性并立即更新视图【英文标题】:Track NSManagedObject property when it was updated and immediately update view 【发布时间】: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 是如何工作的,但是我的应用程序被冻结了。
【问题讨论】:
【参考方案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 获得的对象。对吗? 还是观察不到以上是关于在更新时跟踪 NSManagedObject 属性并立即更新视图的主要内容,如果未能解决你的问题,请参考以下文章
核心数据:访问 NSManagedObject 属性时应用程序崩溃