tejashri tejashri - 5 months ago 164
Objective-C Question

NSURLSession: Synchronous task hangs

I have recently replaced

NSURLConnection
to
NSURLSession
in my code.
As I am using many synchronous url-requests and
NSURLSession
doesn't support one, I used semaphores to make
NSURLSessionDataTask
synchronous.
I referred this link: https://forums.developer.apple.com/thread/11519

I have a singleton 'Network Manger' with
NSURLSession
as a member variable.
NSURLSession
is instantiated only once and tasks are added to it.

But now synchronous request cause performance issues in my app. There are lags and app hangs when synchronous request is sent.

Her is the call to synchronous request:

NSURLResponse *urlResponse;
NSError *error;
id serverResponse=[[MyNetworkManager sharedInstance] synchronousDataTaskWithRequest:request
returningResponse:&urlResponse
error:&error];


Everything works perfectly if I do not make
NetworkManager
as singleton and instantiate it everytime.

MyNetworkManager *manger=[[MyNetworkManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] responseSerializer:nil];
NSURLResponse *urlResponse;
NSError *error;
id *serverResponse=[manger synchronousDataTaskWithRequest:request returningResponse:&urlResponse error:&error];


Notes:

1.Exact Steps: There are total 3 (2 async and 1 sync )
NSURLSessionDataTasks
. Second async task is called in completion handler of first task. Third synchronous task is called from completion handler of second. This third task is blocked forever and code doesn't proceed.

2.Everything is happening on background thread.

Why does synchronous data task work only if it is added to a new
NSURLSession
? Why it doesn't work if added to
NSURLSession
which has already executed two data tasks?

Answer

I was facing the similar issue when I used to synchronus implementation using Semaphore and here is the cause of that issue :

I think that your an HTTP request is causing a redirection, and in the willPerformHTTPRedirection method, you haven't called the completionHandler for the new request. Try implementing the method as :

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
 completionHandler:(void (^)(NSURLRequest *))completionHandler
{
    NSLog(@"willPerformRedirection");
    completionHandler(request);

}