1

i have a method for http connection, which was working fine for me until the server i am trying to have an invalid ssl certificate. Since i am using

[NSURLConnection sendSynchronousRequest:returningResponse:error]

There is no chance to pass authentication challenge by using NSURLConnection delegate methods.

Now, i need to change my service call code as fast as possible. My method returns the data received from the connection, that is the major problem i can not easily change mine to NSURLConnection to initWithRequest:delegate:

My service call method is as follows;

-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type
{
    globalURL = [[NSURL alloc] initWithString:serviceUrl];
    shouldAllowSelfSignedCert = YES;

// if(ISDEBUG) NSLog(@"%@",serviceUrl);

    NSMutableDictionary* json;
    NSURLResponse* response;
    NSData* responseData = [NSMutableData data];

    NSError* error = nil;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:globalURL];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody: [str dataUsingEncoding: NSUTF8StringEncoding]];
    NSString* msgLength = [[NSString alloc] initWithFormat:@"%lu", (unsigned long)[str length]];
    [request addValue:@"text/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request addValue:msgLength forHTTPHeaderField:@"Content-Length"];
    request.timeoutInterval = 180;

     responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];


    if([type isEqualToString:@"image"])
    {
        if(ISDEBUG) NSLog(@"%@",responseData);
        return responseData;
    }
    else
    {
        if(error)
        {
            UIAlertView *message = [[UIAlertView alloc] initWithTitle:NO_WS_CONNECTION message:@"" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];

            if(ISDEBUG) NSLog(@"%@",error);
        }
        else
        {
            if(responseData !=nil)
            {
            json = [NSJSONSerialization
                    JSONObjectWithData:responseData

                    options:kNilOptions
                    error:&error];
            }
            else
            {

            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:NO_WS_CONNECTION delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
            [alert show];
            }
        }

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

       if(ISDEBUG) NSLog(@"%@",responseString);      
   }

   return json;
}

I hope i am clear enough.

What is your advise?

Thanks.

Jay Bhalani
  • 4,142
  • 8
  • 37
  • 50
erdemgc
  • 1,701
  • 3
  • 23
  • 43

1 Answers1

2

You should have a good reason to do it synchronously, so, I will try to help you without changing the flow.

Try wrapping the request into a class where you can implement the request using initWithRequest:delegate: and make the class return the response using block.

You will have something like:

[YourRequestClass requestWithURL:serviceURL callback:^(NSData *yourData, NSError *error){

}];

Ok, at this point you have a new tool that makes ASYNCHRONOUS requests, make the authentication challenge stuff for you and returns the result on a block.

Now, you can simply use dispatch_semaphore to block your thread until the request returns a response ....

-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type {

    __block NSData *myData = nil;

    dispatch_semaphore_t sem = dispatch_semaphore_create(0);

    [YourRequestClass requestWithURL:serviceUrl callback:^(NSData *yourData, NSError *error){
        //ignoring error (this is an example !)
        myData = yourData;
        dispatch_semaphore_signal(sem);
    }];

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    //Use myData and make yourObject here!

    return yourObject;
}

Note that It's just an example, and I'm just trying to pointing you the right way ... I didn't test this code, but I believe it should work as expected!

FormigaNinja
  • 1,571
  • 1
  • 24
  • 36
  • Alternatively, you can add the password to the user's keychain, and synchronous URL requests will use those credentials by default. With that said, moving to an asynchronous style is definitely the right thing to do in the long run. – dgatwood Sep 16 '15 at 00:56