Я столкнулся с этим, потому что наше приложение использовало NSURLConnection sendSynchronousRequest
во многих местах, где это имело смысл, например, когда некоторая обработка происходила в фоновом потоке, иногда требуя дополнительных данных для завершения обработки. Как то так:
// do some processing
NSData * data = someCachedData;
if (data = nil) {
data = [NSURLConnection sendSynchronousRequest....]
someCachedData = data;
}
// Use data for further processing
Если у вас есть что-то вроде 3 разных мест в одном потоке, которые делают это, разбить его на отдельные функции может быть нежелательно (или просто невозможно, если у вас достаточно большая кодовая база).
В какой-то момент нам понадобился делегат для наших подключений (для закрепления SSL-сертификата), и я стал троллить Интернет для поиска решений, и все было в форме: «просто используйте async и не боритесь с платформой! ». Ну, sendSynchronousRequest
существует по причине, вот как воспроизвести его с базовым асинхронным соединением:
+ (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;
}
Опубликовано здесь на случай, если кто-нибудь придет посмотреть, как я.
Обратите внимание, что NSURLConnection sendAsynchrounousRequest
можно заменить любым способом, который вы используете для отправки асинхронного запроса, например, созданием объекта NSURLConnection
с делегатом или чем-то еще.