MagicalRecord:如何在后台保存导入的数据

时间:2014-05-20 19:15:47

标签: ios objective-c core-data magicalrecord

我正在尝试将数据导入Core Data并使用 MagicalRecord 将其保存在后台线程中。

我基本上是想这样做:

__block User *user = nil;
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext)
{
     user = [User MR_findFirstOrCreateByAttribute:@"userId" withValue:userId inContext:localContext];
     [user MR_importValuesForKeysWithObject:responseObject];
}];

[User setCurrentUser:user];

当我进入街区时,用户是正确的。块完成后user NSManagedObject 对象,但没有设置任何属性。

另一方面,这有效:

OEUser *user = [OEUser MR_findFirstOrCreateByAttribute:@"userId" withValue:userId];                               
[user MR_importValuesForKeysWithObject:responseObject];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
[User setCurrentUser:user];

但我想将它保存在后台。


我也试过这个无济于事。

User *user = [User MR_findFirstOrCreateByAttribute:@"userId" withValue:userId];
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext)
{
     User *localUser = [user MR_inContext:localContext];
     [user MR_importValuesForKeysWithObject:responseObject];
}];

[User setCurrentUser:user];

这里的问题似乎是[user MR_inContext:localContext]返回 nil

我对核心数据很新,所以如果我遗漏了一些明显的东西,请耐心等待。

1 个答案:

答案 0 :(得分:4)

当您使用*Wait方法时,您没有获得任何异步性,并且在导入期间您仍将阻止主线程。您确实应该使用块方法,但这样可以确保在正确的线程(创建NSManagedObjectContext的线程)上执行任何Core Data操作。

当你使用saveWithBlockAndWait:时,MagicalRecord会在后台线程上创建一个新的上下文来执行它的工作。然后,这个新创建的上下文将生成到您的块中,并且仅适用于块的范围。您无法在上下文之间传递NSManagedObject,因此您不应该尝试从块外捕获用户。

我可以想象,第二个示例实际上只会在创建新User时失败,因为您调用MR_findFirstOrCreateByAttribute:withValue:会在内存中创建新的NSManagedObject,但这不是坚持到商店因此saveWithBlockAndWait:内没有User从商店拉出来。

正确的方法是

[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
  User *localUser = [User MR_findFirstOrCreateByAttribute:@"userId" 
                                                withValue:userId     
                                                inContext:localContext];
  [user MR_importValuesForKeysWithObject:responseObject];
}];

User *user = [User MR_findFirstByAttribute:@"userId" withValue:userId];

[User setCurrentUser:user];

如上所述,这将阻止主线程,因此您可能需要考虑转移到saveWithBlock:completion:,而不是阻止当前线程在后台执行工作。

更好的是,我会考虑不抓住实际的User对象,而是抓住userId,当人们开始从所有人currentUser访问{{1}}时,这会让您头疼不已。各种线程