Is this the correct usage of an Operation Queue completion block?

Jeremy Mullin picture Jeremy Mullin · May 24, 2011 · Viewed 7.3k times · Source

I'm using Objective-C blocks and Operation Queues for the first time. I'm loading some remote data while the main UI shows a spinner. I'm using a completion block to tell the table to reload its data. As the documentation mentions, the completion block does not run on the main thread, so the table reloads the data but doesn't repaint the view until you do something on the main thread like drag the table.

The solution I'm using now is a dispatch queue, is this the "best" way to refresh the UI from a completion block?

    // define our block that will execute when the task is finished
    void (^jobFinished)(void) = ^{
        // We need the view to be reloaded by the main thread
        dispatch_async(dispatch_get_main_queue(),^{
            [self.tableView reloadData];
        });
    };

    // create the async job
    NSBlockOperation *job = [NSBlockOperation blockOperationWithBlock:getTasks];
    [job setCompletionBlock:jobFinished];

    // put it in the queue for execution
    [_jobQueue addOperation:job];

Update Per @gcamp's suggestion, the completion block now uses the main operation queue instead of GCD:

// define our block that will execute when the task is finished
void (^jobFinished)(void) = ^{
    // We need the view to be reloaded by the main thread
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self.tableView reloadData]; }];
};

Answer

gcamp picture gcamp · May 24, 2011

That's exactly it. You can also use [NSOperationQueue mainQueue] if you want to use an operation queue instead of GCD for your completion block.