Slinky
Slinky

Reputation: 5832

iOS 5 - Capture the return value from a method being called asynchronously

I have a method, fetchFromWeb, that returns an object. I want to call this method asynchronously from GCD. Can someone explain how I would capture the return value from a method being called asynchronously?

Or, should I set the object value and then set up some sort of notification and not explicitly get the return value from this method at all?

Here is what I have and thanks!

        dispatch_async(kBGQueue, ^{


            NSData *data = [NSData dataWithContentsOfURL:kURL];
            [self performSelectorOnMainThread:@selector(fetchFromWeb:) 
                                   withObject:data 
                                waitUntilDone:YES];

            //Need to get the return value from method fetchFromWeb in selector....

        });

Upvotes: 2

Views: 1032

Answers (2)

Matt Wilding
Matt Wilding

Reputation: 20163

Don't use performSelectorOnMainThread:withObject:waitUntilDone:, because you can't get a return from it. Use dispatch_sync with the main dispatch queue instead, which has the same effect as performSelectorOnMainThread:withObject:waitUntilDone:YES.

dispatch_async(kBGQueue, ^{

    NSData *data = [NSData dataWithContentsOfURL:kURL];

    __block id result = nil; // Use the correct type here.
    dispatch_sync(dispatch_get_main_queue(), ^{

        result = [self fetchFromWeb:data];
    });

    // Do something with result here.
});


Edit: I should add that, as noted by Jason Howlin, you shouldn't use dataWithContentsOfURL: in shipping applications. It's okay to use as a quick-n-dirty debugging tool, but NSURLConnection is the correct way to do it. As of iOS 5.0's +sendAsynchronousRequest:queue:completionHandler:, it's not that much harder to use.

Upvotes: 2

user1178952
user1178952

Reputation:

dataWithContentsOfURL is only for file URLs, not Web URLs. Its not asynchronous. Even if you send it off to its own thread using GCD its not the correct way to do it.

If you need to go out to the web, you need to use NSURLConnection.

Use + (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue )queue completionHandler:(void (^)(NSURLResponse, NSData*, NSError*))handler

You were on the right track initially -- you don't want a return value from the method. Let the completion handler block set a property (ivar) with the data you received, and, as you suggested, use a notification at the end of the block to alert you that its done. That notification can fire a method to access the property and you can get at your data object.

Upvotes: 4

Related Questions