我正在尝试将数据导入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 。
我对核心数据很新,所以如果我遗漏了一些明显的东西,请耐心等待。
答案 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}}时,这会让您头疼不已。各种线程