我在coredata中有图像,我正在尝试懒散地加载表格视图。每个单元使用相关核心数据实体的观察者在可用时更新图像。实体中的相关代码如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// The heavy lifting seems to be during firing of the fault and accessing data,
// so i'm trying to do that in the background thread.
UIImage *i = [UIImage imageWithData:self.imageEntity.data];
// I now need to notify observers that the image is ready on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self willChangeValueForKey:@"image"];
image = i;
[self didChangeValueForKey:@"image"];
});
});
该项目使用ARC,我没有收到任何编译器错误或警告,当我运行它时,它有效,直到我快速滚动,然后当我声明i时,我在行上得到一个EXC_BAD_ACCESS。 / p>
我在这里缺少什么?
答案 0 :(得分:7)
显然正在抓取CoreData objects is not thread safe。因此建议使用相同的persistentStoreCoordinator,但使用不同的ObjectContexts。这是我的更新代码,似乎不再崩溃:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@autoreleasepool {
// Create a new context
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init];
// Use an existing coordinator
NSPersistentStoreCoordinator *coordinator = [[DataSource sharedDataSource] persistentStoreCoordinator];
[backgroundContext setPersistentStoreCoordinator:coordinator];
// Getting objectID does not fire the fault, so we grab it but actually fetch the object
// on a background context to be thread safe.
Image *imageEntity = (Image*)[backgroundContext objectWithID:self.imageEntity.objectID];
image = [UIImage imageWithData:imageEntity.data];
// Notify observers that the image is ready on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self willChangeValueForKey:@"image"];
[self didChangeValueForKey:@"image"];
});
}
});
答案 1 :(得分:1)
Dizy,还要记住在代码中创建的Image对象:
UIImage *i = [UIImage imageWithData:self.imageEntity.data];
设置为自动释放。 dispatch_async方法在主队列上运行,因此在主线程运行调度块时,可能会释放为映像分配的内存。
答案 2 :(得分:0)
CoreData不是线程安全的,您必须管理上下文以避免崩溃。 如果您计划大量使用大量并发进程来更新Core Data中的数据,我建议您查看MagicalRecord,这是一个受Active Record of Rails启发并且处理所有这些方面的惊人模式。非常聪明的方式。