objective-cnsurlrequestnsurlsessiondatatasksendasynchronousrequest

Facing an issue with NSURLSessionDataTask with SynchronousRequest in objective-c


Here is my working code with NSURLConnection sendSynchronousRequest :

+ (Inc*)getData:(NSString*)inUUID {
    NSString* urlString = [NSString stringWithFormat:@"/inc/%@", incUUID];
    NSURLRequest* request = [[HttpRequest requestWithRelativePath:urlString] toNSMutableURLRequest];
    NSDictionary* json = [self getJSONForRequest:request];
    return [Inc incFromDictionary:json];
}  
+ (NSDictionary*)getJSONForRequest:(NSURLRequest*)request {
    NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    return  [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
}  

But, sendSynchronousRequest:request is deprecated.

So that, I used NSURLSessionDataTaskinstead of sendSynchronousRequest. Here, is the code which I implemented:

+ (Inc*)getData1:(NSString*)inUUID {
    NSString* urlString = [NSString stringWithFormat:@"/in/%@", inUUID];
    NSURLRequest* request = [[HttpRequest requestWithRelativePath:urlString] toNSMutableURLRequest];
    //NSDictionary* json = [self getJSONForRequest1:request];
    __block NSDictionary* json;

    dispatch_async(dispatch_get_main_queue(), ^{
        [self getJsonResponse1:request success:^(NSDictionary *responseDict) {
            json = [responseDict valueForKeyPath:@"detail"];;
            //return [Inc incFromDictionary:json];

        } failure:^(NSError *error) {
            // error handling here ...
        }];
    });
    return [Inc incFromDictionary:json];
}  
+ (void)getJsonResponse1:(NSURLRequest *)urlStr success:(void (^)(NSDictionary *responseDict))success failure:(void(^)(NSError* error))failure
{
    NSURLSessionDataTask *dataTask1 = [[NSURLSession sharedSession] dataTaskWithRequest:urlStr completionHandler:^(NSData *data, NSURLResponse *response,
                                                                                                                   NSError *error) {
        NSLog(@"%@",data);
        if (error)
            failure(error);
        else {
            NSDictionary *json  = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSLog(@"%@",json);
            success(json);
        }
    }];
    [dataTask1 resume];    // Executed First
}  

The problem is return statement call in getData1 before finish the api call.

Thanks in advance.


Solution

  • As mentioned in the comments you need a completion handler.

    Something like this (untested):

    + (void)getData1:(NSString*)inUUID success:(void (^)(NSDictionary *responseDict))success failure:(void(^)(NSError* error))failure {
        NSString* urlString = [NSString stringWithFormat:@"/in/%@", inUUID];
        NSURLRequest* request = [[HttpRequest requestWithRelativePath:urlString] toNSMutableURLRequest];
    
        [self getJsonResponse1:request success:^(NSDictionary *responseDict) {
            NSDictionary* json = [responseDict valueForKeyPath:@"detail"];
            success(json);
    
        } failure:^(NSError *error) {
            failure(error);
        }];
    }
    
    
    + (void)getJsonResponse1:(NSURLRequest *)urlStr success:(void (^)(NSDictionary *responseDict))success failure:(void(^)(NSError* error))failure
    {
        NSURLSessionDataTask *dataTask1 = [[NSURLSession sharedSession] dataTaskWithRequest:urlStr completionHandler:^(NSData *data, NSURLResponse *response,
                                                                                                                       NSError *error) {
            NSLog(@"%@",data);
            if (error)
                failure(error);
            else {
                NSDictionary *json  = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
                NSLog(@"%@",json);
                success(json);
            }
        }];
        [dataTask1 resume];    // Executed First
    }
    

    And to call

    [MyClass getData1:@"asdf" success:^(NSDictionary *responseDict) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSDictionary *json = [responseDict valueForKeyPath:@"detail"];
            Inc *inc = [Inc incFromDictionary:json];
            // do something witrh `inc`
    
        });
    } failure:^(NSError *error) {
        // error handling here ...
    }];
    

    Consider to use instances and instance methods of your class(es) rather than only class methods.