2012-05-25 7 views
0

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

Я хочу, чтобы метод ожидал завершения асинхронного запроса до его продолжения. Я попытался положить BOOL в методе connectionDidFinishLoading:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    NSLog(@"Succeeded! Received %d bytes of data",[_receivedData length]); 
    [AppDelegate playAudioWithData: _receivedData]; 
    _dataIsReceived = YES; //BOOL 

    // release the connection, and the data object 
    [connection release]; 
    [_receivedData release]; 
} 

А затем положить петлю, а в методе getAndPlaySong:

[self startRequest: correctSongURL]; starts the request asynchronously 

while (!_dataIsReceived) { 
    //do stuff 
} 

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

+0

Не могли бы вы показать код внутри цикла while? Что именно вы хотите сделать, пока URL-адрес загружается? Когда вы говорите: «Я хочу обновить дисплей во время его появления» - что именно вы хотите сделать? Однократное действие или что-то непрерывное? –

+0

Имеет смысл, что он будет висеть, вы зацикливаетесь бесконечно. Вам нужно создать обратный вызов, который будет срабатывать, когда запрос будет завершен. Посмотрите на использование системы уведомлений. – Kaili

ответ

2

Я не хочу показаться грубыми, но то, что вы сделали это худшая вещь. Конечно, приложение зависает, потому что оно имеет бесконечный цикл. Даже если цикл заканчивается, в то время как его в цикле ваше приложение застревает - что, если пользователь пытается что-то сделать с вашим приложением, пока он находится в середине цикла? Вам нужно изменить свое мышление и научиться использовать программирование, управляемое событиями, с помощью конечного автомата. Это парадигма iOS, вам нужно сесть и сделать чтение и обучение, изменить способ, которым вы думаете, и построить свои программы.

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

И это не единственное, что нужно, чтобы сидеть и ждать - что, если пользователь нажимает на экран? Что делать, если пользователь выходит из вашего приложения? Что делать, если ... Ваше приложение должно уметь реагировать на все возможные события и быстро реагировать, соединение - это еще одно событие, на которое он должен слушать и реагировать. Он не может этого сделать, если он находится в цикле.

Никогда не используйте петли в любом месте.

«Я хочу, чтобы метод ожидал завершения асинхронного запроса до его завершения». Нет, вы этого не сделаете - вы никогда не сможете сделать что-либо подобное в приложении с графическим интерфейсом. Функция должна закончить выполнение. Вам нужно реализовать конечный автомат, каждый iOS - это конечный автомат, делегат приложения - это главное, что управляет конечным автоматом, тогда вы добавляете больше состояний и переходов между состоянием, поскольку в программу добавляется больше событий.

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

Извините, если я чувствую себя немного суровым.

0

Два быстрых варианта приходит на ум: Создать метод для вызова для обработки завершенного соединения Используйте NSNotification API для отправки уведомления, когда загрузка завершена

Кроме того, вы можете использовать метод NSURLConnection didReceiveData для обработки данных, поступающих постепенно с сервера.

1

Ваше приложение висит на петле, потому что оно бесконечно.

В iOS, NSURLConnectionDelegate - это способ получить обратный вызов, когда данные получены в соединении и будут уведомлены, когда это будет сделано. И ВСЕ должно выполняться асинхронно и через делегата. Это так, как это делается на iOS.

Результаты при его потоке должны храниться в объекте NSData в методе didRecieveData.

Посмотрите на документах на NSURLConnectionDelegate, но вот пример очертания:

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    int statusCode = [(NSHTTPURLResponse *)response statusCode];  
    if(statusCode == 404) { 
     // Post notification and let concerned parties know something went wrong. 
     [self cleanupConnection]; 
    } 
    else if(statusCode == 200) { 
     // Success do something with the data. 
     requestData = [[NSMutableData alloc] init]; 
    } 
    else { 
     [self cleanupConnection]; 
    } 
} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [requestData appendData:data]; 
} 

-(void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    [self finishedLoadingAppData]; 
} 

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    NSLog(@"Connection Attempt Failed with Error:%@", [error localizedDescription]); 
} 
Смежные вопросы