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]; 

当我在该块内时,用户是正确的。 块完成后, userNSManagedObject对象,但没有设置任何属性。

另一方面,这是工作的:

 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