I ran into this because our app used NSURLConnection sendSynchronousRequest
in quite a few places where it made sense, like having some processing occurring on a background thread occasionally needing extra data to complete the processing. Something like this:
// do some processing
NSData * data = someCachedData;
if (data = nil) {
data = [NSURLConnection sendSynchronousRequest....]
someCachedData = data;
}
// Use data for further processing
If you have something like 3 different places in the same flow that do that, breaking it up into separate functions might not be desirable(or simply not doable if you have a large enough code base).
At some point, we needed to have a delegate for our connections(to do SSL certificate pinning) and I went trolling the internet for solutions and everything was of the form: "just use async and don't fight the framework!". Well, sendSynchronousRequest
exists for a reason, this is how to reproduce it with an underlying async connection:
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse *__autoreleasing *)response error:(NSError *__autoreleasing *)error
{
static NSOperationQueue * requestsQueue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
requestsQueue = [[NSOperationQueue alloc] init];
requestsQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
});
NSCondition * waitLock = [NSCondition new];
[waitLock lock];
__block NSError * returnedError;
__block NSURLResponse * returnedResponse;
__block NSData * returnedData;
__block BOOL done = NO;
[NSURLConnection sendAsynchronousRequest:request
queue:requestsQueue
completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError){
returnedError = connectionError;
returnedResponse = response;
returnedData = data;
[waitLock lock];
done = YES;
[waitLock signal];
[waitLock unlock];
}];
if (!done) {
[waitLock wait];
}
[waitLock unlock];
*response = returnedResponse;
*error = returnedError;
return returnedData;
}
Posted here in case anyone comes looking as I did.
Note that NSURLConnection sendAsynchrounousRequest
can be replaced by whatever way you use to send an async request, like creating an NSURLConnection
object with a delegate or something.