user1079052
user1079052

Reputation: 3833

Using NSUrlConnection but getting beat by race conditions

I have a program that has multiple url request so I used the the code in http://snippets.aktagon.com/snippets/350-How-to-make-asynchronous-HTTP-requests-with-NSURLConnection and put it in it's own class (class B).To call the class I am simple initializing class B in class A, sending a url to class B's get method([classname get:url]) and then getting the server response upon return.

The problem is that I am getting defeated by race conditions due to the fact that the didReceiveData: method is not complete by the time my method is returned.

I have gone through the developer example of using NSUrlConnection and they are updating views once the response finally came in so they didn't have to fight this problem.

Thank you so much for your help.

I need to keep the calls asynchronous due to the number of them I have to make but I am open to any suggestions.

Edit (moved from answer)

I changed the code to GCD based off of a tutorial and I am still getting defeated by the race condition. Here is the code that I am using now: I changed it to GCS based on on your suggestion but I am still getting caught by the race condition. Below is the code that I changed it to and I am calling it by: NSString *responseStringClassA = [InitalizedInstanceOfClassA LogIn:@"username" @"password"];

    //Log into the server
    -(NSString *)logIn: (NSString *) username password:(NSString *) password
     {
     NSString* returnString;
     dispatch_queue_t downloadQueue = dispatch_queue_create("Login", NULL);
     dispatch_async(downloadQueue, ^{
    BOOL success = YES;
    NSString *urlAsString =[NSString stringWithFormat:@""URL HERE];
    NSLog(@"url sent out: %@",  urlAsString);
    NSURL *url = [NSURL URLWithString:urlAsString];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    NSError *error = nil;
    NSData *connectionData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
    NSLog(@"Connection Data: %@", [[NSString alloc] initWithData:connectionData encoding:NSASCIIStringEncoding]);
    [returnString isEqualToString:[NSString stringWithUTF8String:[connectionData bytes]]];
    if ([connectionData length] > 0 && error == nil) {
        //success
        success = YES;
    }
    else if([connectionData length] == 0 && error == nil){
        //nodata 
        success = YES;
    }
    else if(error != nil){
        //error ..
        success = NO;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [returnString isEqualToString:[[NSString alloc] initWithData:connectionData encoding:NSASCIIStringEncoding] ];
    });
});
return returnString;
}                              

Upvotes: 0

Views: 294

Answers (1)

Codo
Codo

Reputation: 78855

It's the very purpose of asynchronous requests that the intial method returns almost immediately without having done the work. Later, when the work has been done, you will be notified and you can access and use the result.

But obviously, you're looking for something else than asynchronous operations. And alternative would be to use synchronous URL requests but run them from separate threads. The best way to achieve this is to use GCD (grand central dispatch).

Note that you may not update the user interface from background threads. Instead, when the URL request has finished and you want to display your results, you have to call performSelectorOnMainThread (part of NSObject) for that.

Upvotes: 1

Related Questions