我正在使用Magical Record来帮助核心数据保存和多线程。
我用GCD启动了一个新线程。在那个新线程中,我检查一个实体是否存在;如果不是,我想创建一个新的并保存它。
如果在非主线程上调用它,saveUsingCurrentThreadContextWithBlock^(NSManagedObjectContext *localContext){}
会返回主线程保存吗?
或者我应该将上下文传递给新线程吗?
编辑:
在主线程上,我创建一个MBProgress指示符并创建一个新线程:
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.mapView animated:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];
if (person == NULL) {
NSLog(@"SEPERATE THREAD | person %@ does not exist, creating", self.user.username);
person = [Person MR_createEntity];
person.name = self.user.username;
person.uid = self.user.UID;
[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) {
[MBProgressHUD hideHUDForView:self.mapView animated:YES];
Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];
if (person) {
NSLog(@"COMPLETION BLOCK | person exists: %@", person.name);
}
}];
}
else {
NSLog(@"SEPERATE THREAD | person %@ does", self.user.username);
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.mapView animated:YES];
});
}
});
(这种保存方法不是持久性,我重启应用程序而我找不到Person实体):
2013-03-12 14:25:44.014 SEPERATE THREAD | person iDealer does not exist, creating
2013-03-12 14:25:44.014 SEPERATE THREAD | thread: <NSThread: 0x84ca720>{name = (null), num = 4}
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Saving <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Parents? 0
2013-03-12 14:25:44.015 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x840ec30) → Save Synchronously? 0
2013-03-12 14:25:44.016 -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x840ec30) Context UNNAMED is about to save. Obtaining permanent IDs for new 1 inserted objects
2013-03-12 14:25:44.132 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x840ec30) → Finished saving: <NSManagedObjectContext (0x840ec30): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-03-12 14:25:44.134 COMPLETION BLOCK | thread: <NSThread: 0x8435f30>{name = (null), num = 1}
2013-03-12 14:25:44.134 COMPLETION BLOCK | person exists: iDealer
答案 0 :(得分:7)
好的,我让它上班了:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Person *person = [Person MR_findFirstByAttribute:NAME withValue:self.user.username];
if (person == NULL) {
[MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext){
Person *localPerson = [Person MR_createInContext:localContext];
localPerson.name = self.user.username;
} completion:^(BOOL success, NSError *error){
[MBProgressHUD hideHUDForView:self.mapView animated:YES];
}];
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.mapView animated:YES];
});
}
});
这可以保存。我不确定这种方法对casademora的意义是不正确的。我无法确定使用此方法与使用saveOnlySelf:completion:
方法之间的区别。
似乎我永远无法使用saveOnlySelf
将上下文保存到持久性存储中。如果我用我的问题中的代码创建它,它将被放置在上下文中。如果我搜索了Person实体,我就能找到它。但是一旦我终止了应用程序并重新启动,该Person实体就不会存在。感觉就像是在保存或合并线程上下文到主/默认上下文,但是没有保存上下文。
编辑:
在更多地使用MR之后,似乎如果在非主线程中使用任何saveOnlySelf
方法,它会将本地上下文合并到默认上下文,但它不会将其保存到持久性商店。如果在完成后检查默认上下文,则新实体确实存在。但是一旦你终止应用程序并重新运行它,它就不存在了。
要合并上下文并保存到商店,您需要调用saveToPersistentStoreAndWait
类型方法之一。
答案 1 :(得分:2)
在当前版本的MagicalRecord中,是的,完成块将返回主线程。但是,此处的方法不正确。现在有更明确的保存方法变体:
saveOnlySelf:completion:
saveToPersistentStore:completion:
在当前版本中查看这些方法。作为提醒,请确保您只使用提供给您的localContext中的托管对象。该工作块可以在任何线程/队列中运行,在这种情况下,您仍然希望对核心数据使用正确的线程管理规则。
答案 2 :(得分:-1)
是的,在主线程中执行完成块。例如:
NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
[newQueue addOperationWithBlock:^{
[MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext) {
// save something
} completion:^(BOOL success, NSError *error) {
// this will execute in the main thread
}];
}];