我正在尝试根据网络提取的属性在后台更新NSManagedObject。难以绕过并发。我试过的是
我的代码看起来像这样
__block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block dispatch_group_t taskGroup = dispatch_group_create();
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
NSArray *assets = [Asset MR_findAllInContext:localContext];
for (Asset *asset in assets) {
dispatch_group_enter(taskGroup);
dispatch_async(queue, ^{
[stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {
//TODO:Check response
NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];
[asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?
dispatch_group_leave(taskGroup);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
//TODO:Error handling here
dispatch_group_leave(taskGroup);
}];
});
}
dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{
NSLog(@"All Tasks are completed");
});
}];
}
当我尝试从网络完成块
更新资产(NSManagedObject)时[asset mapPropertiesFrom:stockData];
我收到了
CoreData无法解决
的错误
我怀疑这是因为完成块在主队列上,我的资产是在私有队列上获取的,你不能从不同的队列访问NSManagedObjects ......但是我不确定这是问题所在如果是如何解决它。
那么,我怎么能完成这样的任务呢?我完全错了吗?
修改
根据以下评论进行了一些更改,但我收到了错误
//Setup Dispatch Group
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t taskGroup = dispatch_group_create();
NSArray *assets = [Asset MR_findAll];
for (Asset *asset in assets) {
dispatch_group_enter(taskGroup);
dispatch_async(queue, ^{
NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
localContext.parentContext = [NSManagedObjectContext MR_defaultContext];
Asset *localAsset = [asset MR_inContext:localContext];
[stockClient updateStockDataFor:localAsset completionHandler:^(NSDictionary *stockData, NSError *error) {
NSManagedObjectContext *responseContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
responseContext.parentContext = [NSManagedObjectContext MR_defaultContext];
Asset *responseAsset = [localAsset MR_inContext:responseContext];
[responseAsset mapPropertiesFrom:stockData];
[responseContext MR_saveToPersistentStoreAndWait];
dispatch_group_leave(taskGroup);
}];
});
}
dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{
NSLog(@"Tasks are Completed");
});
}
错误:
只能在NSManagedObjectContext上使用-performBlock :. 用队列创建。
答案 0 :(得分:2)
使用以下方法包装将在执行块中读取/写入核心数据的任何调用:
- (void)performBlock:(void (^)())block
来自文档:
如果是上下文,则使用此方法将消息发送到托管对象 使用NSPrivateQueueConcurrencyType或初始化 NSMainQueueConcurrencyType。
此方法封装自动释放池和调用 processPendingChanges。
只要您使用此方法进行通话,就不会有任何问题。
我不明白你问题的第二部分,但在我的应用程序中,我一直使用这种方法从网络调用执行更新/读取。或者,您只需将核心数据部分调度到主队列即可。也就是说,在后台执行网络操作以及何时需要核心数据时使用调度队列到主队列。
答案 1 :(得分:1)
就MagicalRecord而言,您将在后台调度后台任务。基本上,您的队列不同步。我建议您使用单个后台队列来保存数据。
尝试这样的事情:
__block dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block dispatch_group_t taskGroup = dispatch_group_create();
NSArray *assets = [Asset MR_findAll];
for (Asset *asset in assets) {
dispatch_group_enter(taskGroup);
dispatch_async(queue, ^{
NSManagedObjectContext = //create a confinement context
Asset *localAsset = [asset MR_inContext:localContext];
[stockClient GET:@"/v1/public/yql" parameters:asset.assetSymbol success:^(NSURLSessionDataTask *task, id responseObject) {
//TODO:Check response
NSManagedObjectContext *responseContext = //create a confinement context
Asset *responseAsset = [localAsset MR_inContext:responseContext];
NSDictionary *stockData = [[[responseObject objectForKey:@"query"] objectForKey:@"results"] objectForKey:@"quote"];
[asset mapPropertiesFrom:stockData];//----------> How do I access the localcontext queue?
[responseContext MR_saveToPersistentStoreAndWait];
dispatch_group_leave(taskGroup);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
//TODO:Error handling here
dispatch_group_leave(taskGroup);
}];
});
}
dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{
NSLog(@"All Tasks are completed");
});
}