Hannes_hal
Hannes_hal

Reputation: 657

iOS threading - callback best practice

I wanted to clean up one of my projects and extracted parts of my source that I often reuse, in a single class. This class handles some requests to a web service, everything is fine so far ;). Until I extracted the code to its own class, I handled those requests with threads and callbacks in the calling class.

Now I have a "best practice" question:

In my code I do something like(simplified):

(void)foo{
   Helper *h =[[Helper alloc]init];
  [h doRequest];
}

doRequest performs a network action(in its own class)and I have to wait until this is request is finished. So I need a callback or something like this.

Should I simply thread doRequest incl. waituntildone=YES?

Do I have to thread the networking in the Helper class too? Or is it enough to call the method threaded something like this:

[NSThread detachNewThreadSelector:@selector(h doRequest) toTarget:self withObject:nil];

What is the best practice to get a callback from doRequest to the caller class after it has completed it’s tasks so that I can handle the returned values from the web service?

Thanks in advance.

Johannes

Upvotes: 0

Views: 4802

Answers (2)

Conor
Conor

Reputation: 1777

I personally prefer calling performSelectorOnMainThread:withObject:waitUntilDone: at the end of any helper threads that need to send information back.

[self performSelectorOnMainThread:@selector(infoFromService:) withObject:aDictionaryWithInfo waitUntilDone:NO];

- (void)infoFromService:(NSDictionary *)aDictionary {
    //Process all the information and update UI
}

Be sure to always use the main thread for any UI updates even if they happen in the middle of the worker thread, for example updating a count of how much information has been downloaded. Use the same technique to call the main thread with the relevant information.

Upvotes: 2

tim
tim

Reputation: 1682

Given doRequest does not return until the request is done you could do

- (void)fooCompletion:(void (^)(void))completion {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        Helper *h =[[Helper alloc]init];
        [h doRequest];
        if (completion) {
            dispatch_async(dispatch_get_main_queue(), ^{
                // doRequest is done
                completion();
            });
        }
    });
}

To call the method:

[self fooCompletion:^{
    // do something after doRequest is done
}];

Upvotes: 3

Related Questions