如何在后台线程上读取核心数据,同步在主线程上读取结果?
如果我在核心数据存储中有100,000个实体,如何在后台线程中访问/加载/获取所有100,000个实体,并且一旦加载/提取访问这些实体在主线程/其他线程上的属性? (例如,显示UICollectionView中的项目)我将使用批处理来避免将所有100,000个加载到内存中 - 但我需要确切知道在初始加载后有多少个内存。如何在后台线程上读取核心数据,同步在主线程上读取结果?
事情是这样的:
// The load occurs on a background thread
[self loadCoreData: ^{
// Once loaded, dispatch back onto the main thread to get the number of
// entities, or I could do something like [self getEntityMatchingProperties:...]
// etc. the point being it accesses entity information that has been loaded but
// on a different thread.
dispatch_async(dispatch_get_main_queue(), ^{
self.title = [self getNumberOfCoreDataEntities];
});
}];
编辑:另一个(更准确的例子):
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// The load occurs on a background thread
[self loadCoreData: ^{
[self.collectionView reloadData];
}];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self numberOfItemsLoadedFromCoreData];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
...
Entity *entity = [self getItemLoadedFromCoreDataAtIndexPath:indexPath];
...
}
在第二个例子中,我试图用一个NSFetchedResultsController
我想 - 是否有任何全这种类型的方法的例子?我所看到的所有这些处理片段都是在主环境中执行取指操作 - 这将在主线程上完成工作。
您似乎在重塑NSFetchedResultsController
,它将处理您在此处需要的一切。你为自己做了不必要的事情。这是一个普遍的需求,苹果公司让你覆盖。使用您的获取请求创建NSFetchedResultsController
,并实现您的集合视图方法,以根据索引路径向其请求对象。作为奖励,NSFetchedResultsController
委托方法可用于更新您的收藏视图,如果基础数据发生变化。
感谢您的回复!我正在嘲笑某些东西,但是我将什么'ManagedObjectContext'传递给'NSFetchedResultsController'?如果它是主要上下文,那么不会在提取发生时阻止UI?在我的应用程序中,这是一个可能持续数秒的获取,绝对不希望只是在那里冻结。 – Zach
它用于UI,因此您通常会使用主要上下文。它也可以自行缓存数据以提高性能,并且它足够聪明,不会将每个对象一次加载到内存中。 –
我很生疏,但你的代码片段似乎只是在主线程上运行getNumberOfCoreDataEntities,而这似乎是击败了目的。我觉得你应该在发送回主线程之前发出这个呼叫。即将该调用的结果存储在变量中,然后将该变量分配给主线程上的self.title。 – ghostatron
@ghostatron我可以理解这一点,当然。也许这是一个糟糕的例子。考虑一个例子,在被加载的视图上,我想开始一个长时间运行的加载/获取操作。然后在一个完全不同的方法中,我想访问核心数据实体的数量,即在“collectionView:numberOfItemsInSection”调用等。 – Zach
如果这只是一个简单的例子,那么我很抱歉。至于跨线程边界传递管理对象,我认为这是一个根本性的禁止。您可以创建自己的类来存储值并将其传递给对象,也可以使用托管对象ID(这是线程安全的)进行重新获取。 – ghostatron