MagicalRecord:如何在后台保存导入的数据
我试图导入数据到核心数据,并保存在一个后台线程与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 。
我对Core Data很新,所以如果我错过了一些明显的东西,请耐心等待。
当您使用*Wait
方法时,您不会获得任何asynchronous性,并且在导入过程中仍然会阻止您的主线程。 你应该确实使用块方法,但是这样做是为了确保任何核心数据操作都在正确的线程(创buildNSManagedObjectContext
的线程)上执行。
当你使用saveWithBlockAndWait:
MagicalRecord在后台线程上创build一个新的上下文来执行它的工作。 这个新创build的上下文然后被放到你的块中,并且只在块的范围内生存。 你不能在上下文之间传递NSManagedObject
,所以你不应该试图从块外部捕获用户。
我可以想象第二个例子实际上只会在创build一个新User
的情况下失败,因为你调用MR_findFirstOrCreateByAttribute:withValue:
它将在内存中创build一个新的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