Retrieving Data from NSURLResponse Completion Block

Looks like I haven't figured out the concept of blocks ...

In my code, I have to get JSON data from asychronous block , which will be returned using the outer method. I googled and found that if the definition of a variable with __block , v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶ _mutability_ of , this variable extends to block .

But for some reason, the returned json object is nil.I wonder why?

 - (NSMutableDictionary *)executeRequestUrlString:(NSString *)urlString { __block NSMutableDictionary *json = nil; NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPShouldHandleCookies:YES]; [request setHTTPMethod:@"GET"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"]; NSString *cookieString = [self.userDefaults objectForKey:SAVED_COOKIE]; [request addValue:cookieString forHTTPHeaderField:@"Cookie"]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]); NSError *error1; NSMutableDictionary * innerJson = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error1]; json = innerJson; }]; return json; } 
+6
source share
3 answers

First, to answer your question:

But for some reason, the returned json object is nil . I wonder why?

The variable you are returning has not been set at the time you return it. You cannot collect the results immediately after the sendAsynchronousRequest:queue:completionHandler: method sendAsynchronousRequest:queue:completionHandler: call must end in the opposite direction before calling your block back and setting the json variable.

Now quickly write down what to do about it: your method tries to convert an asynchronous call to a synchronous one. Try to keep it asynchronous if you can. Instead of waiting for a method that returns NSMutableDictionary* , create a method that takes its own block, and pass the dictionary to this block when the sendAsynchronousRequest: method completes:

 - (void)executeRequestUrlString:(NSString *)urlString withBlock:(void (^)(NSDictionary *jsonData))block { // Prepare for the call ... // Make the call [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]); NSError *error1; NSMutableDictionary * innerJson = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error1 ]; block(innerJson); // Call back the block passed into your method }]; } 
+18
source

When you call sendAsynchronousRequest:queue:completionHandler: you request an asynchronous request. Thus, it queues the request and block and returns immediately. At some point in the future, a request will be made, and after that the completion block will be completed. But by then, return json had long been running.

If you want to be able to return data synchronously, you must make a synchronous request. This will cause this thread to hang until it terminates, so it should not be the main thread.

+2
source

Check the line when converting data coming from the server using the following code:

  NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]); 

if the string is in the correct JSON format, ONLY then your JSON object will be right.

Hope these are hepls !!

0
source

Source: https://habr.com/ru/post/925024/


All Articles