Home > Mobile >  Dispatch semaphore is not working with NSUrlConnection
Dispatch semaphore is not working with NSUrlConnection

Time:10-15

I am handling the legacy code which is using NSUrlConnection to make api requests, but semaphore is blocking the NSUrlConnection delegate methods.

//1

dispatch_semaphore_t semaphore;

//2

semaphore = dispatch_semaphore_create(0);

//3

NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://api2.binance.com/api/v3/ticker/24hr"]];
NSURLRequest *req = [[NSURLRequest alloc]initWithURL:url];
NSURLConnection *con = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
[con start];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

//4 #pragma mark - NSURLConnection Delegate Methods

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"receive response");
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    NSLog(@"receive data");
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"did fail");
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        //Getting your response string
    NSLog(@"did finish loading");
dispatch_semaphore_signal(semaphore);
}

without semaphore wait delegate functions are getting called but when i put semaphore it stopping all delegates

Note: i can't change the legacy code to Urlsession or alamofire/AfNetworking, i can only use NSUrlConnection

CodePudding user response:

NSURLConnection needs a run loop which explains why you can neither use this semaphore pattern (because you will be blocking the thread that the run loop needs) nor just casually move it to a background thread (because a background thread will not have its own run loop running, so you would have to create one and loop on it yourself).

But it is a serious mistake to introduce semaphores. If you are saddled with legacy NSURLConnection library and you wish to add a series of sequential network requests to the project, one should adopt asynchronous patterns, rather than introducing semaphores into the codebase. Semaphores are a mistake as they introduce deadlock risks, offer a really bad UX, risk having the app killed by the watchdog process, and is an inefficient use of system resources. I know how appealing the semaphores might seem at first glance (which is why so many newer developers are so attracted to them), but it is almost always a mistake.

The standard answer is to write a method that runs the NSURLConnection, but has a completion handler block parameter, if one does not yet exist. And then each request’s completion handler block can initiate the next request. There are other, more sophisticated approaches (e.g., wrap this in a custom asynchronous NSOperationQueue and add these to a serial NSOperationQueue) but those are probably beyond the scope of this question.

  • Related