所以我已经阅读了一段时间的堆栈,我意识到我需要制作一个后台核心数据NSManagedObjectContext
,因为我正在加载大量的记录而且我不想锁定UI。
我做的是以下内容:
backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSPersistentStoreCoordinator *store = [[self managedObjectContext] persistentStoreCoordinator];
[backgroundContext setPersistentStoreCoordinator:store];
在我的函数调用中我直接执行:
self.flightsFRC = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:backgroundContext
sectionNameKeyPath:nil
cacheName:@"FlightRecords"];
我的代码目前正在运行,但我感觉它是“坏”的其他地方,我直接访问FRC而不处理任何同步或任何类似于此处迭代通过Fetched Results Controller的任何内容。
FlightRecording *rec = [[[self flightsFRC] fetchedObjects] objectAtIndex:i];
我错过了什么吗?我应该以某种方式通过NSManagedObjectID
加载记录这似乎“太容易了”
答案 0 :(得分:1)
您目前的FRC指向背景上下文。不要这样做。只指向主线程上的上下文。
为了让您的FRC收到有关更改的通知,您实际上需要将后台上下文合并到主线程上下文中。当后台上下文保存时,您的CoreData堆栈对象需要注册通知:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
由于通知可以从其他线程发布,因此我们需要在触发时进行检查以确保我们在主线程上。如果我们已经在那里,那么我们可以在mergeChangesFromContextDidSaveNotification
上调用NSManagedObjectContext
API。
- (void)contextDidSave:(NSNotification *)notification {
if (![NSThread isMainThread]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self contextDidSave:notification];
});
} else {
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
}
由于您的FRC在主要上下文数据发生变化时正在侦听更改,因此FRC将触发其回调,以便您可以在tableview或collectionview中插入/删除/修改记录。
编辑:
听起来您可能没有对后台线程进行任何更改,因为您没有使用后台上下文的performBlock:
或私人队列来完成工作:
[backgroundContext performBlock:^{
// Do your work
NSError *error = nil;
BOOL success = [backgroundContext save:&error];
// error handling
}];