cateof
cateof

Reputation: 6758

Ensure that an async task is completed for iOS

I have a UITableView and a Refresh button in order to get new data from the server (if any).

[self startUpdates]; // animations
[[User myUser] getDataFromServer]; //async
[[User myUser] refreshElements:[[[UpdateContext alloc] initWithContext:data_ with:self with:@selector(endUpdates)] autorelease]];
[self.tableView reloadData];

The code above does not work well, because the getDataFromServer is an asynchronous method that is completed when the server returns the new data (the response). I want to be 100% sure that the refreshElements is being executed only when getDataFromServer gets the response back.

The question is: what is the correct way to do this. I want line 3 to gets executed if and only if line 2 gets the response from the server. Any ideas?

Upvotes: 0

Views: 364

Answers (1)

Aris
Aris

Reputation: 1559

The easiest way would be to change the getDataFromServer method to accept a block that will contain the code that needs to be executed after the data comes from the server. You should ensure that the block will be executed in the Main thread. Here is an example:

Changed method:

- (void)getDataFromServer:(void (^)(NSError * connectionError, NSDictionary *returnData))completionHandler{

    //perform server request
    //...
    //
    NSDictionary * data; //the data from the server
    NSError * connectionError; //possible error
    completionHandler(connectionError, data);
}

And how to call the new method with the block:

[self getDataFromServer:^(NSError *connectionError, NSDictionary *returnData) {
    if (connectionError) {
        //there was an Error
    }else{
        //execute on main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            [[User myUser] refreshElements:[[[UpdateContext alloc] initWithContext:data_ with:self with:@selector(endUpdates)] autorelease]];
            [self.tableView reloadData];
        });
    }
}];

Upvotes: 3

Related Questions