Функции делегата iOS dispatch_async и NSURLConnection не вызываются

Я отредактировал этот пост, чтобы его было проще читать, я думаю.

Мне нужно вызвать NSUrlConnection после того, как я закончу интенсивные манипуляции со строками в блоке dispatch_async.

URL-адрес, который я вызываю, имеет аутентификацию .htaccess, поэтому я не могу использовать синхронное соединение.

Но методы делегата NSURLConnection не вызываются. Я знаю, что URL-адрес загружается примерно через 5 секунд в браузере, и я протестировал код с простым URL-адресом без аутентификации, и это не имеет значения.

Что мешает вызывать методы делегата?

Эта функция выполняет некоторые действия со строками, и для ее завершения требуется некоторое время:

- (void)performSearch {

    // set some defaults and work out if it is a valid search, setting bSearchOk

    if (bSearchOk) {

        // update some interface elements
        self.msgBox.text = @"Translating...";            
        self.plateInput.enabled = NO;
        self.searchProgress.hidden = NO;

        dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            // create a new search
            Search *oPlateSearch = [[Search alloc] initWithTerm:thisTerm];

            // ...
            // perform search... this calls a variety of slow and intensive functions
            // ...

            self.aFinalPlates = [oPlateSearch.aValidated copy];
            self.aCurrentPlates = [oPlateSearch.aFinals copy];        

            dispatch_async( dispatch_get_main_queue(), ^{                 
                [oPlateSearch release];              

                // make ajax call to check if plates can be bought
                [self getPrices];                 
            });
        });

    } else {
        // hide results
        self.searchResults.hidden = YES;
    }

}

И это тот, который вызывается ближе к концу блока выше

/* call to get plate availability and prices */
-(void) getPrices {
    // set return message
    self.msgBox.text = @"Getting prices and availability";

    // ...
    // then I build my strRequest var, which is a valid working URL
    // ...

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strRequest]];

    NSURLConnection *loginConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];

    NSLog('This will get logged');

    if(loginConnection) {
        NSLog('This will also get logged');
        self.jsonSearchResponse = [[[NSMutableData data] retain] autorelease];
        NSLog('And this will get logged, so it's not throwing errors');
    } else {
        NSLog(@"Failed to get search results");
    }
}

Обновление: я тоже пробовал это, так как это было принято в ответ на другой аналогичный вопрос, но это не сработало:

NSURLConnection *loginConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[loginConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[loginConnection start];

На основе этого вопроса: Почему делегат NSURLConnection методы не вызываются при использовании глобальной очереди отправки?


person Pete    schedule 20.01.2012    source источник


Ответы (3)


Кто-то с форума iphonedevsdk.com ответил мне на это:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/97415-dispatch_async-nsurlconnection.html

Ответ заключался в использовании:

 [self performSelectorOnMainThread:@selector(getPrices) withObject:Nil waitUntilDone:NO];
person Pete    schedule 27.01.2012
comment
Почему это решает проблему? - person Rey Gonzales; 31.01.2013
comment
Я не совсем уверен, но, судя по имени функции PerformSelectorOnMainThread, когда поток, который я запускаю, завершается, он вызывает метод основного потока программы. - person Pete; 01.02.2013
comment
Может быть, вы действительно не решили проблему, потому что теперь вы вызываете getPrices в основном потоке, а не в глобальной очереди отправки, как вы изначально хотели? - person Jon Conner; 07.09.2013

Я начал сообщение SO, в котором показано, как использовать NSURLConnection с dispatch_async и настроить NSRunLoop

оболочка блокировки NSURLConnection, реализованная с семафорами

Фрагмент кода, который вас заинтересует:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    [NSURLConnection connectionWithRequest:request delegate:self];

    while(!self.finished) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
});

и в connectionDidFinishLoading установите finished на YES:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    self.finish = YES;
}
person quentinadam    schedule 05.12.2012

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

person zoul    schedule 20.01.2012
comment
Я пробовал это, не работает, я боюсь. Я переместил релиз в методы connectionDidFinishLoading и connectionDidFail, но он работает точно так же - person Pete; 20.01.2012