magicalpanda / MagicalRecord

Super Awesome Easy Fetching for Core Data!
Other
10.8k stars 1.79k forks source link

Completion block called before all saving is done (saveWithBlock) #1003

Open sulfo opened 9 years ago

sulfo commented 9 years ago

First of all, I'm not sure if it's a real bug, or me who don't know how to implement it correctly, but I find it strange that the completion block is called before everything has been saved.

I have the following code:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

    NSDictionary *jsonData = [responseObject valueForKey:@"responses"];
    [User importFromObject:jsonData inContext:localContext];

    NSArray *orders = [responseObject valueForKeyPath:@"responses.orders"];
    [Order importFromArray:orders inContext:localContext];

} completion:^(BOOL success, NSError *error) {
    if(error) {
        NSLog(@"Failed to save data");
        return;
    }
    NSLog(@"Saving done.");
    successful();
}];

So for me it looks alright. I'm not been able to find other examples online on how I should use the import, so I guess it's the correct way for using saveWithBlock with imports. After the completion has send the block successful back a segue is done so I can show the imported data.

Here's the log from xCode

2015-05-06 14:55:57.261 xxxx[43159:9057742] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0xfeea04) -> Created Context UNNAMED
2015-05-06 14:55:57.262 xxxx[43159:9057742] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0xfeea04) Set Root Saving Context: <NSManagedObjectContext: 0x7ae6cb20>
2015-05-06 14:55:57.263 xxxx[43159:9057742] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0xfeea04) Created Main Queue Context: <NSManagedObjectContext: 0x7ae73ee0>
2015-05-06 14:55:57.263 xxxx[43159:9057742] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0xfeea04) Set Default Context: <NSManagedObjectContext: 0x7ae73ee0>
2015-05-06 14:55:58.915 xxxx[43159:9057742] POST 'xxxx'
2015-05-06 14:55:59.939 xxxx[43159:9057742] 200 'xxxx' [1.0249 s]
2015-05-06 14:55:59.957 xxxx[43159:9057742] POST 'xxxx'
2015-05-06 14:56:00.702 xxxx[43159:9057742] 200 'xxxx' [0.7454 s]
2015-05-06 14:56:10.534 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7af24cb0) → Saving <NSManagedObjectContext (0x7af24cb0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2015-05-06 14:56:10.535 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7af24cb0) → Save Parents? 1
2015-05-06 14:56:10.535 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7af24cb0) → Save Synchronously? 0
2015-05-06 14:56:10.541 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7af24cb0) Context UNNAMED is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-06 14:56:10.750 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Saving <NSManagedObjectContext (0x7ae6cb20): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-06 14:56:10.750 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Save Parents? 1
2015-05-06 14:56:10.750 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Save Synchronously? 0
2015-05-06 14:56:16.200 xxxx[43159:9058195] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ae6cb20) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-06 14:56:16.232 xxxx[43159:9058195] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7ae6cb20) → Finished saving: <NSManagedObjectContext (0x7ae6cb20): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***   <--- My user has now been saved
2015-05-06 14:56:16.233 xxxx[43159:9057742] Saving done.
2015-05-06 14:56:16.233 xxxx[43159:9057742] All data has been setup successfully
2015-05-06 14:56:16.255 xxxx[43159:9057742] Perform Segue To LoginSucessSegue from LoginViewController
2015-05-06 14:56:36.208 xxxx[43159:9057742] No data found. Show pull down to refresh
2015-05-06 14:56:36.208 xxxx[43159:9057742] No data found. Show pull down to refresh
2015-05-06 14:56:36.210 xxxx[43159:9057742] No data found. Show pull down to refresh
2015-05-06 14:56:36.211 xxxx[43159:9057742] No data found. Show pull down to refresh
2015-05-06 14:56:45.083 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae3b550) → Saving <NSManagedObjectContext (0x7ae3b550): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2015-05-06 14:56:45.083 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae3b550) → Save Parents? 1
2015-05-06 14:56:45.084 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae3b550) → Save Synchronously? 0
2015-05-06 14:56:45.084 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ae3b550) Context UNNAMED is about to save. Obtaining permanent IDs for new 9 inserted objects
2015-05-06 14:56:45.087 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Saving <NSManagedObjectContext (0x7ae6cb20): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-06 14:56:45.087 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Save Parents? 1
2015-05-06 14:56:45.091 xxxx[43159:9058146] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ae6cb20) → Save Synchronously? 0
2015-05-06 14:56:45.093 xxxx[43159:9060610] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ae6cb20) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 9 inserted objects
2015-05-06 14:56:45.096 xxxx[43159:9060610] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7ae6cb20) → Finished saving: <NSManagedObjectContext (0x7ae6cb20): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD *** <--- Orders has first now been saved??

As the log tells, the completion block is been called right after my import of user is finished, and therefor it doing the segue too early, before all my data has been saved.

Is it a bug or wrong implementation? I'm pretty new with Objective-C, so it could be a stupid newbie mistake.

I've also tried to split them up into two blocks of saveWithBlock and hoped it would fix it, but it was the same problem.

Alydyn commented 9 years ago

Something interesting is going on... your two groups of log statements have 2 different memory addresses for the UNNAMED contexts. From just the code that you posted there should only be 1 set of save log statements with an UNNAMED and ROOT context.

What version or branch of MagicalRecord are you using? And are you sure this isn't getting called twice?

sulfo commented 9 years ago

At the moment I'm using version 2.2. Yes, I'm sure this is not been called twice. Here is some more code, that might give a better understanding of what is going one:

[authApi attemptUserAuthTokenWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

    if (self.rememberMe.on == YES) {
        [UICKeyChainStore setString:self.emailTextField.text forKey:@"Email"];
        [UICKeyChainStore setString:self.passwordTextField.text forKey:@"Password"];
    }

    [userApi getUserDetailsWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

            NSDictionary *jsonData = [responseObject valueForKey:@"responses"];
            [User importFromObject:jsonData inContext:localContext];

            NSArray *orders = [responseObject valueForKeyPath:@"responses.orders"];
            [Order importFromArray:orders inContext:localContext];

        } completion:^(BOOL success, NSError *error) {
            if(error) {
                NSLog(@"Failed to save data");
                return;
            }
            NSLog(@"Saving done.");
            NSLog(@"All data has been setup sucessfully");
            [self.activityIndicator stopAnimating];
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];

            NSLog(@"Perform Segue To LoginSucessSegue from LoginViewController");
            [self performSegueWithIdentifier: @"LoginSucessSegue" sender: self];
        }];

    } failure:^(NSString *error) {
        [self.activityIndicator stopAnimating];
        [[UIApplication sharedApplication] endIgnoringInteractionEvents];

        // Create an alert view and show it
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"An error acurred" message:@"We are not sure why, but try again." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];

        return;
    }];

} failure:^(NSString *error) {
    // Stop the activity indicator
    [self.activityIndicator stopAnimating];
    [[UIApplication sharedApplication] endIgnoringInteractionEvents];

    // Create an alert view and show it
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Login Error" message:@"The email or password you entered is incorrect." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];

    [alert show];

    NSLog(@"Error log: %@", error);
}];

This is my code for almost the hole function. I've removed some class between classes just for making it more easy to read, but I still have the same problem.

Here's the Xcode log for running this code:

2015-05-07 21:22:44.427 xxxx[50457:11822390] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0x1018a04) -> Created Context UNNAMED
2015-05-07 21:22:44.428 xxxx[50457:11822390] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x1018a04) Set Root Saving Context: <NSManagedObjectContext: 0x7aff1310>
2015-05-07 21:22:44.428 xxxx[50457:11822390] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0x1018a04) Created Main Queue Context: <NSManagedObjectContext: 0x7aff58c0>
2015-05-07 21:22:44.429 xxxx[50457:11822390] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x1018a04) Set Default Context: <NSManagedObjectContext: 0x7aff58c0>
2015-05-07 21:22:45.924 xxxx[50457:11822390] POST 'xxxx'
2015-05-07 21:22:46.958 xxxx[50457:11822390] 200 'xxxx' [1.0341 s] <-- This 200 is a auth success
2015-05-07 21:22:46.978 xxxx[50457:11822390] POST 'xxxx'
2015-05-07 21:22:47.594 xxxx[50457:11822390] 200 'xxxx' [0.6166 s] <-- This 200 is a batch of information for the import
2015-05-07 21:22:47.615 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7c22eda0) → Saving <NSManagedObjectContext (0x7c22eda0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2015-05-07 21:22:47.615 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7c22eda0) → Save Parents? 1
2015-05-07 21:22:47.615 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7c22eda0) → Save Synchronously? 0
2015-05-07 21:22:47.616 xxxx[50457:11822797] Importing order
2015-05-07 21:22:47.616 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7c22eda0) Context UNNAMED is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-07 21:22:47.619 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Saving <NSManagedObjectContext (0x7aff1310): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-07 21:22:47.619 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Save Parents? 1
2015-05-07 21:22:47.620 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Save Synchronously? 0
2015-05-07 21:22:47.626 xxxx[50457:11822837] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7aff1310) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 2 inserted objects
2015-05-07 21:22:47.628 xxxx[50457:11822837] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7aff1310) → Finished saving: <NSManagedObjectContext (0x7aff1310): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-07 21:22:47.628 xxxx[50457:11822390] Saving done.
2015-05-07 21:22:47.628 xxxx[50457:11822390] All data has been setup sucessfully
2015-05-07 21:22:47.629 xxxx[50457:11822390] Perform Segue To LoginSucessSegue from LoginViewController
2015-05-07 21:22:47.633 xxxx[50457:11822797] Importing order
2015-05-07 21:22:47.643 xxxx[50457:11822797] Importing order
2015-05-07 21:22:47.661 xxxx[50457:11822390] No data found. Show pull down to refresh
2015-05-07 21:22:47.662 xxxx[50457:11822390] No data found. Show pull down to refresh
2015-05-07 21:22:47.664 xxxx[50457:11822390] No data found. Show pull down to refresh
2015-05-07 21:22:47.664 xxxx[50457:11822390] No data found. Show pull down to refresh
2015-05-07 21:22:47.674 xxxx[50457:11822797] Importing order
2015-05-07 21:22:47.680 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aebf420) → Saving <NSManagedObjectContext (0x7aebf420): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2015-05-07 21:22:47.681 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aebf420) → Save Parents? 1
2015-05-07 21:22:47.683 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aebf420) → Save Synchronously? 0
2015-05-07 21:22:47.685 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7aebf420) Context UNNAMED is about to save. Obtaining permanent IDs for new 9 inserted objects
2015-05-07 21:22:47.689 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Saving <NSManagedObjectContext (0x7aff1310): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
2015-05-07 21:22:47.689 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Save Parents? 1
2015-05-07 21:22:47.714 xxxx[50457:11822797] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7aff1310) → Save Synchronously? 0
2015-05-07 21:22:47.714 xxxx[50457:11822844] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7aff1310) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 9 inserted objects
2015-05-07 21:22:47.722 xxxx[50457:11822844] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7aff1310) → Finished saving: <NSManagedObjectContext (0x7aff1310): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***

I can try to run another version of MagicalRecord if you suggest it :smile:

"Importing order" is in my entity class called Order.m where the -(void)willImport:(id)data is triggered

Alydyn commented 9 years ago

Use v2.3.0 beta5 instead.

You definitely have multiple different contexts being created. If you don't already you should also turn on Core Data concurrency debugging.

sulfo commented 9 years ago

So I updated to the version you suggested, and I think it works now. All the logging from MagicalRecord has despaired, and I've not been successful with by attempts to turn it back on.

I've not turned on Core Data concurrency debugging, but it has been done now.

seanLee commented 9 years ago

@Alydyn i used pod "MagicalRecord", :git => 'https://github.com/magicalpanda/MagicalRecord.git', :branch => 'develop' first to import the v2.3.0 beta5.But lately I run pod update It shows I changed to v2.3.0 and met the same issue.How can I import v2.3.0 beta5 by cocoapods?

Alydyn commented 9 years ago

You'll need to reference a specific tag. Ex.: pod 'MagicalRecord', :git => 'https://github.com/magicalpanda/MagicalRecord.git', :tag =>'v2.3.0-beta.5' Be aware that I do not use CocoaPods so the above has not been tested. You can find more help on this page of cocoapods.org.

seanLee commented 9 years ago

@Alydyn thank you so much.Have solved my problem.

umairxiq commented 7 years ago

Still having same issue in new version. Any solution yet?