App getting stuck in dispatch_async

776 views Asked by At

This is my code:

        LoadViewController *loadingViewController = [[LoadViewController alloc] initWithNibName:@"LoadViewController" bundle:nil];
[self.view addSubview:loadingViewController.view];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) , ^{
    [Util deleteAllObjects:@"Unit"];
    for (NSDictionary *eachUnit in serviceData) {
        //insert in DB
        AppDelegate* appDelegate = [AppDelegate sharedAppDelegate];
        NSManagedObjectContext *context = appDelegate.managedObjectContext;
        Unit *unit = [NSEntityDescription insertNewObjectForEntityForName:@"Unit" inManagedObjectContext:context];

        unit.id_unidade = [eachUnit objectForKey:@"id"];
        unit.title = [eachUnit objectForKey:@"title"];
        unit.image = [eachUnit objectForKey:@"image"];
        unit.address = [eachUnit objectForKey:@"address"];
        unit.desc = [eachUnit objectForKey:@"desc"];
        unit.coord = [eachUnit objectForKey:@"coord"];

        NSError *error;

        if (![context save:&error]) {
            NSLog(@"Ops,fail: %@", [error localizedDescription]);
        }
    }
    NSLog(@"before");
    [self fillUnits];
    NSLog(@"after");

    dispatch_async(dispatch_get_main_queue(), ^(void) {
        NSLog(@"reload");
        [self.tableView reloadData];
        [loadingViewController.view removeFromSuperview];
        NSLog(@"after reload");

    });
});

It shows until the NSLog(@"after"), but never gets on the NSLog(@"reload"). Any clues??

1

There are 1 answers

7
CouchDeveloper On

In your completion handler, you need to ensure that all methods send to a managed object or to a managed object context are executed on their respective execution context using performBlock: or performBlockAndWait::

    NSManagedObjectContext *context = appDelegate.managedObjectContext;
    [context performBlockAndWait:^{
        Unit *unit = [NSEntityDescription insertNewObjectForEntityForName:@"Unit"  inManagedObjectContext:context];

        unit.id_unidade = [eachUnit objectForKey:@"id"];
        unit.title = [eachUnit objectForKey:@"title"];
        unit.image = [eachUnit objectForKey:@"image"];
        unit.address = [eachUnit objectForKey:@"address"];
        unit.desc = [eachUnit objectForKey:@"desc"];
        unit.coord = [eachUnit objectForKey:@"coord"];

        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Ops,fail: %@", [error localizedDescription]);
        }
    }];

If your managed object will be accessed in the main thread, it's mandatory that the execution context equals the main thread.

You can read more in the Apple Docs: NSManagedObjectContext Reference, especially chapter "Concurrency".