在我的应用程序中,我使用 CoreData 来存储和使用 NSFetchedResultsController 显示数据。
我按照 raywenderlich 的教程完成了它,它有很多代码 - 但它通常可以正常工作 - 将在需要时发布其中的一部分。我坚持一个我无法理解的问题。
与 NSFetchedResultsController 结合的 UITableView 中显示的数据可以在后台更新 - 这就是我的问题开始的地方。
我正在使用 Pull-to-refresh 方法并在单独的线程上在后台开始下载。它使用为该线程创建的自己的 NSManagedObjectContext 并在创建所有对象后保存它。
这是代码:
- (void)refresh:(id)sender
{
[ServerConnection downloadContactsForToken:token success:^(NSDictionary* responseObject)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSManagedObjectContext* context = [[[AppManager sharedAppManager] createManagedObjectContext] retain];
NSArray* responseContacts = responseObject[@"contacts"];
[responseContacts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
//ContactDB is NSManagedObject
[[[ContactDB alloc] initWithDictionary:obj andContext:context] autorelease];
}];
[context save:nil];
[context release];
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl endRefreshing];
});
});
}];
}
根据我在 Apple 文档中阅读的内容,在主线程 NSManagedObjectContext 上检测这些更改的正确方法是:
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
}
- (void)managedObjectContextDidSave:(NSNotification *)notification {
dispatch_async(dispatch_get_main_queue(), ^{
if(notification.object != [[AppManager sharedAppManager] managedObjectContext]) {
[[[AppManager sharedAppManager] managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
});
}
基本上,当我收到有关任何 managedObjectContext 更改的通知时,我会将更改合并到主线程上下文。它通常可以工作,但是在我开始分析之后,我发现合并到所描述进程中的所有对象都不会被释放。
当我在主线程上做所有事情时——它可以工作——当我滚动 UITableView 时,它们会按预期被释放。
我找到了一种解决方法,我正在打电话:
[[[AppManager sharedAppManager] managedObjectContext] reset];
合并完成后:
[[[AppManager sharedAppManager] managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
[[[AppManager sharedAppManager] managedObjectContext] reset];
但我不知道为什么我必须这样做,以及这是否会破坏其他东西。也许有一种更好的方法可以在后台刷新数据,而我完全走错了路。