Как дождаться, пока асинхронный запрос вернет данные, прежде чем возвращать значение

Я отправил асинхронный запрос на веб-сайт, используя следующий код:

NSMutableURLRequest *requestSiteToSendData = [NSMutableURLRequest requestWithURL:[[NSURL alloc]initWithString:@"www.example.com"] cachePolicy:NSURLRequestReloadIgnoringCacheData  timeoutInterval:30];
NSURLConnection *connectionToSiteToSendData = [[NSURLConnection alloc]initWithRequest:requestSiteToSendData delegate:self];

Затем я использовал следующий метод, определенный внутри NSURLConnectionDelegate, для получения и анализа данных после завершения выборки данных.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    //parse 'data'
    NSString *parsedData = [self parseDataWithData:data];
}

И затем в методе, в котором я отправляю асинхронный запрос, я возвращаю parsedData. Но возврат должен происходить только после завершения выборки данных и, следовательно, выполнения синтаксического анализа. Я знаю, что возникает вопрос, если это то, что мне нужно, то почему я не использую синхронный запрос. Это потому, что я не хочу, чтобы мои другие методы зависали, когда загрузка происходит в фоновом режиме.


person Harikrishnan    schedule 12.08.2013    source источник


Ответы (4)


Быстрый ответ: если он асинхронный, вы не хотите ждать асинхронный метод. Одним из лучших вариантов будет:

  • Вызывающий объект, которому нужны данные, должен установить себя как объект, который запускает асинхронный метод, а в didReceiveData вы вызываете такой метод, как updateData:(NSString *)parsedData, который обрабатывает только что полученные данные.

  • Объект, вызывающий метод, должен использовать KVO для наблюдения за любыми изменениями свойства объекта, который запускает асинхронный метод.

Скажите мне, если вам нужна дополнительная информация.

person DCMaxxx    schedule 12.08.2013
comment
Фактическая проблема заключается в том, что значение должно быть возвращено только после завершения загрузки, а все остальные методы должны работать без зависаний. Но в моем случае return вызывается до завершения загрузки. Надеюсь, я ясно. Пожалуйста, спросите, есть ли что-то, что вы не поняли в вопросе. - person Harikrishnan; 12.08.2013
comment
Да, я понимаю, что это значит, и это нормально: поскольку запрос выполняется асинхронно, остальная часть функции продолжается после завершения асинхронного вызова. Я понимаю, что вы хотите, чтобы ваш метод ждал, пока он действительно не завершится, но это НЕ является хорошей идеей или практикой. Сервер может никогда не ответить и сделать ваше приложение не отвечающим, а также по многим другим причинам. Вы должны справиться с этим, используя свой собственный делегат или KVO. Если вам понадобится помощь с этим, я был бы рад помочь. Вы можете подождать, используя ответ Армаана Незнакомца, НО Я НЕ ДЕЛАЛ ЭТОГО. (не отвечающее приложение и т. д.). - person DCMaxxx; 12.08.2013
comment
Хорошо.. проблема была решена с помощью самодельного делегата. Спасибо. - person Harikrishnan; 13.08.2013

Асинхронные запросы выполняются в отдельном потоке, поэтому нам не нужно беспокоиться об обработке блокировки представления. Если вы хотите отправить синхронный запрос, вам нужно использовать GCD для достижения того же. И различные другие детали, такие как количество отправленных/полученных данных и т. д., не будут доступны в синхронном запросе.

Синхронный запрос полезен, если следующее состояние вашего кода зависит от данных, полученных в ответ на запрос.

person Ashwani    schedule 12.08.2013
comment
Фактическая проблема заключается в том, что значение должно быть возвращено только после завершения загрузки, а все остальные методы должны работать без зависаний. Но в моем случае return вызывается до завершения загрузки. Надеюсь, я ясно. Пожалуйста, спросите, есть ли что-то, что вы не поняли в вопросе. - person Harikrishnan; 12.08.2013
comment
Затем создайте синхронный запрос вместо асинхронного, используя [NSThread]. И вызовите это, когда загрузка завершится. Это не приведет к зависанию вашего приложения. - person Ashwani; 12.08.2013

Насколько я понимаю, вы хотите, чтобы данные возвращались после завершения веб-вызова. поэтому я бы предложил создать любой метод для веб-вызова, который возвращает NSData, и сделать что-то вроде этого:

NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];  
NSData *responseData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&urlResponse error:&error];  

if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
       // return responseData from here.
}
else {
        NSLog(@"%d",[urlResponse statusCode]);
        NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        NSLog(@"%@",result);

}

и вы не хотите повесить свой View. поэтому вызовите этот метод в фоновом потоке. так:

[self performSelectorInBackground:@selector(WebCallMethod) withObject:nil];

Надеюсь, поможет!!

person Armaan Stranger    schedule 12.08.2013
comment
Таким образом, основной принцип здесь заключается в том, что синхронный запрос, работающий в фоновом режиме, будет иметь тот же эффект, что и асинхронный запрос? Даже если это так, даже если запросы загружают его в фоновом режиме, он все равно будет возвращать данные, верно? - person Harikrishnan; 12.08.2013
comment
@HarikrishnanT, ты прав. но я дал еще один вариант. оба работают одинаково. так что это только его выбор. - person Armaan Stranger; 12.08.2013

У вас есть этот метод делегата, который будет выполняться, когда вся загрузка с сервера будет успешно завершена. Используйте этот метод для выполнения оставшегося процесса.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
}

Хорошо, этот метод запускается, когда все данные получены. Что вам нужно сделать, так это собрать все данные из метода делегата -didReceiveData, а затем использовать их для анализа в этом методе.

Обязательный к прочтению документ для вас

person Lithu T.V    schedule 12.08.2013
comment
Я пробовал даже это, но данные возвращаются до завершения загрузки. Я пробовал рекурсивный вызов до тех пор, пока данные не будут получены, но это привело к сбою приложения, и ничего не произошло. Фактическая проблема заключается в том, что значение должно быть возвращено только после завершения загрузки, а все остальные методы должны работать без зависаний. Надеюсь, я ясно. Пожалуйста, спросите, есть ли что-то, что вы не поняли в вопросе. - person Harikrishnan; 12.08.2013
comment
Просмотрите правки и просмотрите ссылку для большей ясности, над которой вы пытаетесь - person Lithu T.V; 12.08.2013