问题
When someone logins my app, a call with a JSON response is made, and I use this data to import it into Core Data with MagicalRecord.
After all importing is done, a block named success is called to let my LoginViewController know everything was fine, and stopping the UIActivityIndicatorView
, so it can make a segue.
It Segue to a new ViewController and it has a UITableView
to display the freshly imported data.
My problem is, that this success block is been called before MagicalRecord is done with the savings. Therefor the UITableView
has not received the Orders objects to display yet.
Here's my implementation of saveWithBlockAndWait
block is as following:
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
NSDictionary *users = [responseObject valueForKeyPath:@"responses.user"];
[User importFromObject:users inContext:localContext];
NSArray *orders = [responseObject valueForKeyPath:@"responses.orders"];
[Order importFromArray:orders inContext:localContext];
NSLog(@"SAVING DONE");
}];
In my OrdersViewController
(witch is the ViewController there's been segue too) is another NSLog
, and it's here the problem might be.
The output from Xcode shows that SAVING DONE is been called, but right after my AFNetworking calls. That means all the data is not saved, and not ready to display - even with the saveWithBlockAndWait
. Also the output shows that there's 0 rows.
The app works perfect on my second launch. It's only on the first login I have this problem
2015-05-04 19:16:31.617 xxxxx[35555:5569667] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0xff4a04) -> Created Context UNNAMED
2015-05-04 19:16:31.618 xxxxx[35555:5569667] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0xff4a04) Set Root Saving Context: <NSManagedObjectContext: 0x7aecdf10>
2015-05-04 19:16:31.618 xxxxx[35555:5569667] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0xff4a04) Created Main Queue Context: <NSManagedObjectContext: 0x7aff4280>
2015-05-04 19:16:31.618 xxxxx[35555:5569667] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0xff4a04) Set Default Context: <NSManagedObjectContext: 0x7aff4280>
2015-05-04 19:16:46.104 xxxxx[35555:5569667] POST 'secret'
2015-05-04 19:16:47.237 xxxxx[35555:5569667] 200 'secret' [1.1324 s]
2015-05-04 19:16:47.258 xxxxx[35555:5569667] POST 'secret'
2015-05-04 19:16:47.880 xxxxx[35555:5569667] 200 'secret' [0.6215 s]
2015-05-04 19:16:47.901 xxxxx[35555:5569667] SAVING DONE
2015-05-04 19:16:47.902 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae251e0) → Saving <NSManagedObjectContext (0x7ae251e0): *** UNNAMED ***> on *** MAIN THREAD ***
2015-05-04 19:16:47.903 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae251e0) → Save Parents? 1
2015-05-04 19:16:47.903 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae251e0) → Save Synchronously? 1
2015-05-04 19:16:47.903 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ae251e0) Context UNNAMED is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-04 19:16:47.906 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Saving <NSManagedObjectContext (0x7aecdf10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2015-05-04 19:16:47.906 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Save Parents? 1
2015-05-04 19:16:47.906 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Save Synchronously? 1
2015-05-04 19:16:47.907 xxxxx[35555:5569667] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7aecdf10) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-04 19:16:47.909 xxxxx[35555:5569667] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7aecdf10) → Finished saving: <NSManagedObjectContext (0x7aecdf10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2015-05-04 19:16:47.909 xxxxx[35555:5569667] All data has been setup sucessfully
2015-05-04 19:16:47.909 xxxxx[35555:5569667] Perform Segue To LoginSucessSegue from LoginViewController
2015-05-04 19:16:47.945 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae19130) → Saving <NSManagedObjectContext (0x7ae19130): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2015-05-04 19:16:47.952 xxxxx[35555:5569667] Number of rows: 0
2015-05-04 19:16:47.957 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae19130) → Save Parents? 1
2015-05-04 19:16:47.957 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae19130) → Save Synchronously? 0
2015-05-04 19:16:47.958 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ae19130) Context UNNAMED is about to save. Obtaining permanent IDs for new 4 inserted objects
2015-05-04 19:16:47.962 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Saving <NSManagedObjectContext (0x7aecdf10): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-04 19:16:47.963 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Save Parents? 1
2015-05-04 19:16:48.023 xxxxx[35555:5570918] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aecdf10) → Save Synchronously? 0
2015-05-04 19:16:48.024 xxxxx[35555:5570924] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7aecdf10) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 4 inserted objects
2015-05-04 19:16:48.026 xxxxx[35555:5570924] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7aecdf10) → Finished saving: <NSManagedObjectContext (0x7aecdf10): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
Is the saveWithBlockAndWait
been implemented wrong, since it's not working for me? An advice or solution on how to solve this would be awesome.
回答1:
Your log seems correct. First it runs your block, then it saves everything to database, then current thread continues execution.
You use synchronous method. Synchronous methods block current thread until they finish execution. If you want to update your interface you have to do this right after saveWithBlockAndWait
or use async version of "save" method that provides completion handler.
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
NSDictionary *users = [responseObject valueForKeyPath:@"responses.user"];
[User importFromObject:users inContext:localContext];
NSArray *orders = [responseObject valueForKeyPath:@"responses.orders"];
[Order importFromArray:orders inContext:localContext];
}];
NSLog(@"Saving done.");
Generally, it is better to use async methods to avoid blocking main thread.
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
// create or update CoreData models
} completion:^(BOOL contextDidSave, NSError *error) {
if(error) {
NSLog(@"Failed to save data");
return;
}
NSLog(@"Saving done.");
[self.activityIndicator stopAnimating];
}];
来源:https://stackoverflow.com/questions/30036222/magicalrecord-finish-block-before-everything-is-saved-on-import