很多时候,我在我的应用程序中遇到这样的情况,我正在推送视图控制器并从核心数据中获取对象以填充 UI。现在我通常在主线程上的 viewDidLoad 中执行此操作,并且我确信有更好的方法来执行此操作,可能在不同的线程上。
如果确实线程是要走的路,我在目标c中没有很多线程经验,所以如果有人能给我展示代码示例,我将不胜感激。
而且我知道核心数据不是线程安全的,所以为了安全起见,我应该做任何额外的工作吗?
很多时候,我在我的应用程序中遇到这样的情况,我正在推送视图控制器并从核心数据中获取对象以填充 UI。现在我通常在主线程上的 viewDidLoad 中执行此操作,并且我确信有更好的方法来执行此操作,可能在不同的线程上。
如果确实线程是要走的路,我在目标c中没有很多线程经验,所以如果有人能给我展示代码示例,我将不胜感激。
而且我知道核心数据不是线程安全的,所以为了安全起见,我应该做任何额外的工作吗?
您可能应该使用 NSFetchedResultsController。它将为您管理批处理,并且只加载您当时需要的内容。它不仅适用于表格视图。您可以在没有单独线程的情况下执行此操作(只要您的数据库不太大,并且您的 fetch 没有需要访问数据库中每条记录的过于复杂的谓词)。
作为 FRC 的替代方案,或者在需要所有记录的情况下,您可以使用单独的线程,该线程将获取对象,然后将它们呈现给主线程。
这些是在单个 SO 答案中难以解释的概念,因此如果仍然没有意义,请查阅 Core Data Concurrency Programming Guide。
或者,如果您想全部加载并进行一些控制,您可以执行以下操作。注意:我认为这种双 MOC 模式无论如何都是要走的路,因为无论如何它都更容易做背景。就此而言,如果您使用 UIManagedDocument,无论如何您都可以免费获得其中的大部分内容。
请注意,这可能需要更长的整体加载时间,但它会释放 UI 线程。
NSManagedObjectContext *workerMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerMoc.persistentStoreCoordinator = psc;
// The "mainMoc" will be a child of the worker
NSManagedObjectContext *mainMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
mainMoc.parentContext = workerMoc;
然后在加载...
// The actual work will run in the background on the worker queue
// The "worker" queue will do the fetching and faulting, then pass object IDs
// to the mainMoc, which will fault its MOs from the parent
[workerMoc performBlock:^{
NSFetchRequest *fetchRequest = // Create fetch request
NSArray *fetchResults = [workerMoc executeFetchRequest:fetchRequest error:0];
[fetchResults enumerateObjectsUsingBlock:^(NSManagedObject *obj, NSUInteger idx, BOOL *stop) {
// Probably want to fault the object in before going to mainMoc
// since that can also take some time...
// Can also "batch" them in some small number of objects.
NSManagedObjectID *objectID = obj.objectID;
[mainMoc performBlock:^{
NSManagedObject *fetchedObject = [mainMoc objectWithID:objectID];
// Do something with it now that you are back on the main thread...
}];
}
}];