Асинхронный NSURLConnection в отдельном потоке не в состоянии вызвать методы делегата - PullRequest
6 голосов
/ 29 февраля 2012

Я запускаю NSURLConnection в отдельном потоке (я знаю, что он асинхронный и работает при работе в основном потоке), но он не выполняет вызовы делегатов, даже когда я передаю родительский поток в качестве делегата. Кто-нибудь знает, как это сделать?

Код:

-(void)startConnectionWithUrlPath:(NSString*)URLpath {

//initiates the download connection - setup
NSURL *myURL = [[NSURL alloc] initWithString:URLpath];

myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[myURL release];


//initiates the download connection on a seperate thread
[NSThread detachNewThreadSelector:@selector(startDownloading:) toTarget:self withObject:self];

}


-(void)startDownloading:(id)parentThread {

 NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];

 [NSURLConnection connectionWithRequest:myURLRequest delegate:parentThread];
 //The delegate methods are setup in the rest of the class but they are never getting called...

 [pool drain];
}

EDIT *

Причина, по которой мне нужно запустить NSURLConnection в отдельном потоке, заключается в том, что я загружаю что-то в свое приложение для iPhone, и загрузка отменяется, когда пользователь блокирует экран (это нормально, если пользователь просто нажимает кнопку «Домой» и приложение выходит на задний план). Я понимаю, что это связано с тем, что я выполняю соединение асинхронно в главном потоке, а не в отдельном.

Я также пробовал этот код (НЕ в отдельном потоке) при запуске NSURLConnection:

  NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:myURLRequest delegate:self startImmediately:NO];
   [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   [connection start];
   [connection release];

Но у меня та же проблема с загрузкой, которая отменяется при блокировке экрана.

* UPDATE

Чтобы добавить ответ Томаса ниже (обратите внимание, что ответ Джеймса Вебстера также верен в отношении выхода из потока), документы Apple объясняют: «Состояние приостановлено - приложение находится в фоновом режиме, но не выполняет код. Система автоматически переводит приложения в это состояние и не уведомляет их об этом. Пока приложение приостановлено, приложение остается в памяти, но не выполняет никакого кода».

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

Поэтому я приостанавливаю (сохраняю определенную информацию и отменяю NSURLConnection) все загрузки, когда приложение переходит в фоновый режим, и возобновляю его с заголовком HTTP Range, когда оно снова становится активным. Это обходной путь, который подходит, но не идеален, так как загрузка не происходит в фоновом режиме, что негативно влияет на пользовательский опыт ... Облом.

Ответы [ 2 ]

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

Поскольку NSURLConnection является асинхронным, конец метода -startDownloading достигается немедленно, и поток завершается.

Вы действительно должны запланировать свое соединение в главном цикле выполнения (или использовать GCD).

Еще одна проблема - блокировка устройства. Когда устройство заблокировано, ваше приложение приостанавливается для экономии заряда аккумулятора. Вероятно, вы можете запросить дополнительное время при приостановке , чтобы завершить загрузку.

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

Я думаю, что ваша проблема может заключаться в том, что NSURLConnection был освобожден, как только вы выйдете из сообщения startDownloading: (или, точнее, когда ваш пул авто-выпуска истощается)

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

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

-(void)startConnectionWithUrlPath:(NSString*)URLpath {

    //initiates the download connection - setup
    NSURL *myURL = [[NSURL alloc] initWithString:URLpath];

    myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
    [myURL release];

    [NSURLConnection connectionWithRequest:myURLRequest delegate:self];
}
...