Nic Hubbard
Nic Hubbard

Reputation: 42173

Objective-C Blocks and variable scope

I would like to set the value of an NSData object within my block. Can someone let me know what I have done wrong here?

// Data
__block NSData *data = nil;

[ZSURLConnection performRequestWithUrl:wsdlURL xmlString:xml completionHandler:^(NSData *response, NSError *error) {

    // Handle the error
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
    } else {
        data = response;
    }//end

}];//end block

if (data) {
    NSString *d = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
    NSLog(@"DATA --- %@", d);
}

return data;

Why can't I assign the response to data and then retrieve it outside of my block?

Upvotes: 3

Views: 1849

Answers (2)

Jonathan Grynspan
Jonathan Grynspan

Reputation: 43472

Because the block runs asynchronously, after the rest of your method. Either rewrite your calling code to work with the asynchronous loading, or find a way to perform the block's work synchronously. I don't know what ZSURLConnection is, but check to see if it has a version of the "perform..." method that doesn't run in the background.

Upvotes: 7

Rob Napier
Rob Napier

Reputation: 299623

performRequestWithUrl:xmlString:completionHandler: is not a synchronous method. It sets up an asynchronous request and then immediately returns. The rest of your method runs and returns.

When the request completes, only then does it run your block, which assigns data and then immediately throws it away.

Were this a synchronous method, your routine would block pending an expensive network operation. Were this on the main thread, your entire app would hang. ZSURLConnection (and NSURLConnection) is designed to avoid that.

Upvotes: 3

Related Questions