MagicalRecord + AFNetworking + NSFetchedResultsController, how to make it work?

In my application, I am trying to use MagicalRecord + AFNetworking + NSFetchedResultsController together to sync data and dynamically display it in a map or tableView.

Check out the download code:

+ (void) getDataWithCompletionBlock: (void (^)(void)) block {

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL_GET_DATA]];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
            for (NSDictionary *dict in JSON) {
                [MyModel createOrUpdateMyModelFromDict:[dict mutableCopy]];
            }

            [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveInBackgroundCompletion:^{
                [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveNestedContexts];

                block();
            }];
        });

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        DDLogError(@"getDataWithCompletionBlock FAILURE: %@", error);
    }];

    [operation start];
}

      

I load data with AFJSONRequestOperation

, then create models using GCD and a background thread, save the context for the current thread, and execute successBlock

(MagicalRecord runs successBlock

on dispatch_get_main_queue()

, so it gets called on the GUI thread.

Is this synchronization pattern ok? Because sometimes (more often on a real device than in a simulator), I get some errors NSFetchedResultsController

like "no object at index: in section by index" or "CoreData cannot execute error ...".

They all say there is something wrong with Core Data and multi-threaded environment. Has anyone tried connecting all three of these collaboration tools? If so, what am I missing? Do you have any good code examples for this architecture?

+3


source to share


1 answer


I would suggest using:

[MagicalRecord saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block];

It handles threads for you, so you don't have to worry about keeping anything in the parent context from the background context.



I highly recommend that you read this blog post (written by MagicalRecord creator Saul Mora): IMPORT DATA MADE EASY . This is a very good background on how MagicalRecord works and an example of how to use it.

If you set up your data model correctly, you can indeed have a MagicalRecord for the entire display, and all you have to do is call importFromObject:

inside the block saveWithBlock:

, and you don't have to worry about dealing with the display. In the article above, I'll go into detail on how to get it right, but it will take some practice.

+2


source







All Articles