acecapades
acecapades

Reputation: 895

Dealing with Blocks, completion handlers, dispatch_async vs dispatch_sync

I'm executing an online fetch of data in a thread and I want to do something immediately after the block is executed.

Here's my code:

- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
    });
    dispatch_release(fetchQ); 

    NSLog(@"done checking");
    //do something here
}

The thing is dispatch_async returns immediately and "done checking" prints immediately even before the block is done executing. How do I solve this?

Upvotes: 4

Views: 7338

Answers (2)

gregheo
gregheo

Reputation: 4270

I think it's an architectural issue. The tasks are something like:

  1. edit toolbar
  2. fetchImonggoItemsDataIntoDocument
  3. do something else

If these must be done exactly in order then I don't quite understand the use of blocks or queues; just run the statements after each other and you'll be set.

Otherwise, alternative #1 would be to use dispatch_sync rather than dispatch_async. Again, I'm not quite sure what the benefit of using a queue would be but there it is.

Alternative #2 would be to use a callback from the block. Something like:

- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
        [self doneChecking]; // <-- NOTE! call the callback
    });
    dispatch_release(fetchQ); 
}

// NOTE! refresh: has been split up into two methods
- (void)doneChecking:
    NSLog(@"done checking");
    //do something here
}

Upvotes: 4

nacho4d
nacho4d

Reputation: 45088

As others have already suggested, this is probably what you need.

NSArray *items = [iMonggoFetcher fetchImonggoData:IMONGGO_GENERIC_URL_FOR_PRODUCTS withFormat:@"json" withDateRangeArgs:args];
[document.managedObjectContext performBlock:^{
    for (NSDictionary *itemInfo in items){
        [Product productWithImonggoInfo:itemInfo inManagedObjectContext:document.managedObjectContext];
    }
    // Put here what you need :)
}];

Upvotes: 1

Related Questions