NSURLConnection sendSynchronousRequest - фон для переднего плана - PullRequest
6 голосов
/ 02 ноября 2011

Я использую sendSynchronousRequest для получения данных с сервера. Я знаю, что синхронный будет ждать, пока данные, полученные для этого запроса.

Но проблема возникает, когда пользователь по ошибке вводит какой-то несуществующий URL и затем пытается получить ответ. В этом случае, если пользователь переходит в фоновый режим, а затем выходит на передний план, он показывает только черный экран. Он показывает только строку состояния. Также его не показаны какие-либо фоновые приложения. Мне нужно нажать кнопку «Домой», чтобы выйти из приложения.

На симуляторе, через 1+ минуты он показывает мне сообщение "Время ожидания истекло" (без сбоев).

На устройстве в течение 1 минуты происходит сбой приложения.

Любое предложение. Любая помощь. Это действительно серьезная проблема в моем приложении.

Спасибо.

Ответы [ 9 ]

14 голосов
/ 06 марта 2012

Так же, как сказал Жюльен, сторожевой таймер убивает ваше приложение. Чтобы ответить на несколько вопросов:

  • почему это происходит только на симуляторе? Потому что, когда вы отлаживаете, сторожевой таймер оставляет ваше приложение в покое, это может занять некоторое время.
  • почему это происходит только тогда, когда пользователь вводит неверный URL? Из-за системного тайм-аута система будет продолжать попытки в течение 60 секунд, если не сможет найти сервер.
  • так проблема синхронная против асинхронной? Нет, проблема в потоке, вы можете сделать ту же операцию в фоновом потоке, просто не делайте этого в основном потоке, и сторожевой таймер оставит вас в покое.
  • почему экран черный при запуске приложения? Помните, что вы делаете блокировку в основном потоке, который рисует ...

Надеюсь, что это все. Дайте мне знать, если я что-то пропустил.

8 голосов
/ 06 марта 2012

Почему бы не установить тайм-аут для вашего соединения?

NSString *urlString = TEST_CONNECTION;
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSURLRequest *request = [NSURLRequest
                         requestWithURL:[NSURL URLWithString:urlString]
                         cachePolicy:NSURLRequestReloadIgnoringCacheData
                         timeoutInterval:5.0];


NSData *conn = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

Это должно освободить синхронное ожидание через несколько секунд, что должно решить вашу проблему без использования асинхронного вызова (который иногда неправильное решение)

Я знаю, что это работает правильно, потому что именно так я проверяю, подключен ли я к определенной VPN (где флаги достижимости полностью терпят неудачу).

3 голосов
/ 05 марта 2012

вам следует взглянуть на эту статью: https://developer.apple.com/library/ios/#qa/qa1693/_index.html

iOs содержит сторожевой таймер , если ваше приложение заблокировано на длительное время при выполнении операции в главном потоке, этабудет убит(для более подробной информации о Watchdog: http://en.wikipedia.org/wiki/Watchdog_timer)

Так что, если вы хотите что-то скачать, не загружайте это в основной теме.

2 голосов
/ 22 января 2015

СВЯЗЬ

UIImage *image = [self.imgCache objectForKey:urlString];
if(!image){
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0];


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURLResponse *response = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
        NSLog(@"%@",response);
        UIImage *img = [UIImage imageWithData:data];
        //

        if(img)
        {
            dispatch_sync(dispatch_get_main_queue(), ^{
                [self.imgCache setObject:img forKey:urlString];
                completionBlock(img);
            });
        }
    });

}
else{
    completionBlock(image);
}
0 голосов
/ 05 марта 2012

Вы можете проверить доступность URL-адреса перед началом запроса.У Apple есть Reachability методы для этого.Но проще использовать обертку.Например, ASIReachability.

0 голосов
/ 02 марта 2012

Попробуйте это:

#import "ASIHTTPRequest.h"

//In a method
[self performSelectorInBackground:@selector(DownLoadImageInBackground:) withObject:imgUrlArr];  


-(void) DownLoadImageInBackground:(NSArray *)imgUrlArr1  
{
    NSURL * url = [Image URL];

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request startAsynchronous];
}

-(void)requestFailed:(ASIHTTPRequest *)request

{

    NSLog(@"URL Fail : %@",request.url);

    NSError *error = [request error];

       // you can give here alert too..
}

-(void)requestFinished:(ASIHTTPRequest *)request

{

    NSData *responseData = [request responseData];
    UIImage *imgInBackground = [[UIImage alloc]
                         initWithData:responseData];
    [imageView setImage: imgInBackground];

}

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

0 голосов
/ 01 марта 2012

Я думаю, что сначала вы должны проверить пользовательские данные, независимо от того, верны они или нет, а затем, только если они верны, отправляет запрос, в противном случае предлагает пользователю «пожалуйста, введите правильные данные» ...

или

, когда ваш анализ данных в ответ не удался.Вы также можете создать метод делегирования протокола, например, FinishWithError, чтобы получить свой последний пользовательский интерфейс.

0 голосов
/ 29 февраля 2012

Я думаю, что приложение вылетает, потому что вы не получаете никаких данных, когда пользователь вводит неправильно URL, и вы используете этот 'возвращенный' nil NSData для выполнения действий.

Я думаю, что это будетисправить вашу проблему

NSData *data=[NSURLConnection sendSynchronousRequest:request 
                                   returningResponse:&response 
                                               error:&error];
if(data!=nil){
    /// 
} else {
   NSLog(@"NO DATA");
}
0 голосов
/ 02 ноября 2011

используйте класс ASIHttpRequest вместо NSURLConnection, это не что иное, как обертка вокруг NSURLConnection и имеет очень простые обратные вызовы, вы также можете установить время для завершения запроса. Пожалуйста, перейдите по этой ссылке для получения дополнительной информации http://allseeing -i.com / ASIHTTPRequest /

...