0

我正在使用 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];
            });
    }
});

(这种保存方法不是持久化,我重启app找不到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
4

3 回答 3

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类型方法。

于 2013-03-12T20:29:58.643 回答
2

在当前版本的 MagicalRecord 中,是的,完成块将返回到主线程。但是,您这里的方法是不正确的。现在有更明确的 save 方法变体:

saveOnlySelf:completion:
saveToPersistentStore:completion:

在当前版本中查看这些方法。提醒一下,请确保您只使用提供给您的 localContext 中的托管对象。该工作块可以在任何线程/队列中运行,在这种情况下,您仍然希望对核心数据使用正确的线程管理规则。

于 2013-03-11T21:41:33.533 回答
-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
    }];
}];
于 2013-03-11T21:41:21.643 回答