2010-08-21 4 views
0

Я был остановлен в своей работе небольшой проблемой: мое приложение содержит некоторые веб-запросы, которые почти сразу же выполняются, если используется Wi-Fi соединение, однако им нужно пару секунд, чтобы закончить в случае 3G или даже EDGE-соединения. В течение этого периода я хотел бы указать пользователю, что запрос выполняется, например. путем отображения сообщения на ярлыке.Предупреждение при выполнении веб-запроса?

код выглядит примерно так:

-(void)query{ 
    alertLabel.text = @"in progress…"; 

    // the query follows... 
    NSString *queryURLstring = [NSString stringWithFormat:@"http://xyz.xyz"]; 
    NSURL *queryURL = [[NSURL alloc] initWithString:queryURLstring]; 
    NSString *receivedData = [[NSString alloc] initWithContentsOfURL:queryURL]; 
    //query done 

    alertLabel.text = @""; 
} 

Что происходит на практике является то, что, когда запрос выполняется, пользователь может на самом деле не делать ничего. Когда запрашиваемые данные будут получены, текст «in progress ...» появится на мгновение, и он немедленно исчезнет. Я не могу понять, что это не так, как должно работать. Текст должен отображаться на этикетке перед выполнением запроса и должен быть очищен только после завершения. Кто-нибудь сталкивался с такой проблемой? Можете ли вы порекомендовать решение? Спасибо за все предложения! Miv

+0

См. Мои изменения по вашему вопросу. Я создал код, чтобы он выглядел как код. Каждая строка кода должна начинаться с не менее 4 пробелов. –

ответ

0

Существует несколько решений для вашей проблемы.
@ Эйко объяснила проблему и причины очень хорошо.

Следующая является одним из возможных решений (с минимальным количеством изменений кода):

Просто запустите ваш метод query в фоновом потоке, как это:

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

И заменить alertLabel.text = @"in progress…"; по:

[alertLabel performSelectorOnMainThread:@selector(setText:) withObject:@"in progress…" waitUntilDone:NO]; 

[то же самое о alertLabel.text = @"";]


Было бы лучше, если бы вы:

  • Добавить 2 метода: - (void)showLoadingWithText:(id)loadingText; и - (void)hideLoading;.
  • Вызовите эти методы в основном потоке (вместо выполнения селекторов непосредственно на этикетке).
  • Добавьте дополнительные индикаторы активности, например [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; (отобразит индикатор загрузки в заголовке) или ваш пользовательский номер UIActivityIndicatorView (вы должны найти его где-то рядом с alertLabel).
+0

Michael, спасибо! Предлагаемое решение является хорошим, однако мне пришлось реализовать следующий путь: 1. Показать метку предупреждения - в фоновом потоке 2. Начать загрузку в основной теме 3. По завершении (успешное или ошибочное) удалите ярлык - в фоновом потоке То есть: - (BOOL) запрос: (myDataT *) данные { [alertLabel performSelectorInBackground: @selector (SetText :) withObject: @ "в процессе ..."]; // запрос ... // запрос делается // обработка полученных данных ... данных-> результат = ...; // ... [alertLabel performSelectorInBackground: @selector (setText :) withObject: @ ""]; return retVal; } – cactusdev

+0

@cactusdev, это как раз противоположное тому, что нужно делать. Все взаимодействие с пользовательским интерфейсом (например, setText для метки) должно выполняться в основном потоке, и вся обработка в режиме тяжелой/длинной (например, синхронное соединение) должна выполняться в фоновом режиме. –

+0

Майкл, да, конечно, вы правы, но на самом деле я не знаю, как реализовать противоположную (то есть нормальную) операцию. Кроме того, проблема, о которой я упоминал в своем ответе на ответ Эйко (основной поток должен был ждать данных от запроса), другая проблема заключается в том, что попытка выполнить запрос в bkgnd приводит к сбою приложения ... Это не ошибка неизвестного происхождения но, конечно, моя ошибка в коде - просто нужно выяснить, что не так ... – cactusdev

0

Вы должны загрузить данные асинхронно.

  1. показать этикетку ALERT
  2. Начало ЗАГРУЖАЯ асинхронно
  3. После отделка (успешно или ошибка) удалить метку.

Если что-то занимает больше времени, чем ожидалось, и вы блокируете основную нить, будьте готовы автоматически убить все приложение - вы определенно не хотите, чтобы это произошло!

Что касается обновлений на экране. Обновления происходят только в конце текущей итерации цикла выполнения, поэтому это вполне ожидаемое поведение. (Честно говоря, я немного удивлен, что тест виден вообще).

+0

Вместо/в дополнение к представлению предупреждения вы также можете использовать UIProgressView: http://developer.apple.com/iphone/library/documentation/uikit/reference/UIProgressView_Class/Reference/Reference.html – Kalle

+0

Ну, он на самом деле использует нешумную этикетку. Но представление прогресса - хорошее предложение или представление активности. – Eiko

+0

Eiko, Спасибо за ваш ответ. Однако я решил немного по-другому, чем вы предлагали. Моя новая проблема: метод запроса возвращает результат (как параметр) в объекте. Приложение было сконструировано для работы по одному потоку ... Если запрос запускает фон, основной поток будет пропускать данные, которые будут доступны только при завершении запроса. Как я могу заставить основной поток ждать? Повторяющийся таймер установлен на 0,1 с для проверки того, что данные уже возвращены ...? На самом деле у меня нет другой идеи, но должен быть лучший способ ее решить. – cactusdev

Смежные вопросы