0

Im following tutorial and i typed method like follow:

+(void)downlaodDataFromURL:(NSURL *)url withCompletionHandler:(void (^)(NSData *))completionHandler{ // Instantiate a session configuration object NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Instantiate a session object NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; // Create a data task object to perform the data downloading NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error != nil){ // If any error occurs then just display its description on the console NSLog(@" %@", [error localizedDescription]); } else { //If no errors occurs, check the HTTP status code. NSInteger HTTPStatusCode = [(NSHTTPURLResponse*)response statusCode]; //If it's other than 200, then show it on console. if (HTTPStatusCode != 200){ NSLog(@"HTTP status code = %d", HTTPStatusCode); } //Call the completion handler with the returned data on the main thread. [[NSOperationQueue mainQueue] addOperationWithBlock:^{ completionHandler (data); completionHandler (data); }]; } }]; //Resume the task [task resume]; } 

I have 2 question:

First - in method declaration i've seen following: withCompletionHandler:(void (^)(NSData *))completionHandler. I have never seen construction like (void (^). In my understanding of method syntax, we have arguments and type, that method should return or not, but what is that? I've never seen voidin place like this, and what is (^)? I know, ^ means block, but what about that construction?

Second - in

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ completionHandler (data); }]; 

I see completionHandler (data);. There is round brackets, completionHandler is declared in top method, and data is obvious the data, we got from the URL. But what exactly that does and what is - completionHandler? When i look at (void (^)(NSData *))completionHandler i think that completionHandler is object of NSData type. That make no sense for me. I guess, i just can't understand syntax correctly.

Could u please provide an explanation? I know the whole meaning of this, but this 2 chunks of code confuse me.. Thank you!

EDIT:

In my viewController.m i have a method declared as follow:

-(void)getCountryInfo{ //Prepare the URL that we'll get the country info data from. NSString *URLString = [NSString stringWithFormat:@"http://api.geonames.org/countryInfoJSON?username=Necrosoft&country=%@", self.countryCode]; NSURL *url = [NSURL URLWithString:URLString]; [AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data){ //Check if any data returned if (data != nil){ //Convert the returned data into a dictionary NSError *error; NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; if (error != nil){ NSLog(@"%@", [error localizedDescription]); } else { self.countryDetailsDictionary = [[returnedDict objectForKey:@"geonames"] objectAtIndex:0]; NSLog(@"%@", self.countryDetailsDictionary); //Set the country name to the respective label. self.lblCountry.text = [NSString stringWithFormat:@" %@ (%@)", [self.countryDetailsDictionary objectForKey:@"countryName"], [self.countryDetailsDictionary objectForKey:@"countryCode"]]; //Reload the table view. [self.tblCountryDetails reloadData]; //Show the table view. self.tblCountryDetails.hidden = NO; } } }]; } 

There is a class method call that was described above:

 [AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data){ ...// there is code pasted above 

So, if i understand correct, completionHandler (data); invokation defined as follow:

 //Check if any data returned if (data != nil){ //Convert the returned data into a dictionary NSError *error; NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; if (error != nil){ NSLog(@"%@", [error localizedDescription]); } else { self.countryDetailsDictionary = [[returnedDict objectForKey:@"geonames"] objectAtIndex:0]; NSLog(@"%@", self.countryDetailsDictionary); //Set the country name to the respective label. self.lblCountry.text = [NSString stringWithFormat:@" %@ (%@)", [self.countryDetailsDictionary objectForKey:@"countryName"], [self.countryDetailsDictionary objectForKey:@"countryCode"]]; //Reload the table view. [self.tblCountryDetails reloadData]; //Show the table view. self.tblCountryDetails.hidden = NO; 

When data is an NSData object which we successfully download with :

 AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data) 

Am i right?

1
  • Look for Blocks in Obkectice-C Commented Feb 8, 2015 at 16:45

1 Answer 1

1

withCompletionHandler:(void (^)(NSData *))completionHandler

Objective-C methods declare arguments with C typecast syntax. So, this can be thought of as:

withCompletionHandler:(SomeType)completionHandler 

where SomeType is void (^)(NSData *). This is, admittedly, ugly and confusing syntax. What it means is: block pointer for a block which takes an NSData* argument and doesn't return anything (returns void).

Consider:

void foo(NSData *); 

That's clearly a declaration of a function which takes an NSData* argument and doesn't return anything.

Next:

void (^foo)(NSData *); 

That's a declaration of a block variable named foo which takes an NSData* argument and doesn't return anything.

Now, to make it just a type, drop the name foo:

void (^)(NSData *) 

That's the type of foo in my last example and the completionHandler argument in your code.

Hopefully that helps answer your second question. The code:

completionHandler (data); 

is an invocation of the completionHandler block. It passes data as the argument to the block, which matches the known type of the block.

Sign up to request clarification or add additional context in comments.

10 Comments

Thank you Ken! Now its all clear for me! I appreciate your help a lot!
btw, what exactly [[NSOperationQueue mainQueue] addOperationWithBlock:^{ completionHandler (data); }]; (based on presented code)? I still not figure that out..Document says: This method adds a single block to the receiver by first wrapping it in an operation object. What does that mean anyway?
NSOperationQueue is a queue of operation objects (instances of NSOperation or subclasses). It feeds those operations into worker threads based on readiness, priority, and concurrency limits. Operations encapsulate some task and track various state. One subclass of NSOperation is NSBlockOperation, where the work done by the operation consists of one or more blocks. The -addOperationWithBlock: method creates an operation object (similar to NSBlockOperation) which uses the passed-in block as its task. It adds that operation to the queue.
thank you for detailed answer. If i understand correct. block implementation is declared in other place of code (in tutorial its declared in another class method).
I think you're right, although I'm not entirely sure I understood you. In your code [AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data){ ... }];, the part ^(NSData *data){ ... } is a block that you're passing in as an argument to +downlaodDataFromURL:withCompletionHandler:. Within +downlaodDataFromURL:withCompletionHandler:, that block is referred to by completionHandler. The statement completionHandler(data) is an invocation of that block, passing the data that was downloaded. That causes your code in ^(NSData *data){ ... } to be run.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.