0

У меня есть UIBarButtonItem под названием «Обновить данные». Когда пользователь нажимает на нее, приложение должно обновить свои данные. Что происходит при нажатии этой кнопки, запускаются веб-службы и приводятся данные xml, и они имеют порядок 30000-40000 записей. Поэтому, чтобы предотвратить зависание пользовательского интерфейса, я написал фоновый поток и сделал там загрузку.UIAlertview висит, когда поток в фоновом режиме загружает данные

- (void)refreshDataAction 
{ 
NSLog(@"Refresh Data"); 
//Put up an alert box indicating user to wait while data is loading. 

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading" 
                 message:@"Please wait while data is being refreshed." 
                 delegate:self 
               cancelButtonTitle:@"OK" 
              otherButtonTitles:nil, nil]; 
alert.tag = 10; 
[alert show]; 
} 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
NSLog(@"hit in clickedbuttonatindex alertview at 259"); 
self.refreshActIndicator.hidden = NO; 
[self.refreshActIndicator startAnimating]; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
             (unsigned long)NULL), ^(void) { 
    [self getAllCustomerValues]; 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 
}); 
} 

Как вы можете видеть, появляется предупреждение. Я нажимаю «ОК», и окно все еще там «черненое» и его висит там на экране. И через 7-8 секунд окно исчезает, и анимация начинается с индикатора активности. Моя цель - получить что-то вроде этого. 1.User нажимает кнопку обновления данных. 2. Появляется окно просмотра. 3.User нажимает OK. окно 4.Alert исчезает и сразу начинает работать фоновый поток, и я вижу индикатор активности/анимацию.

Пользователь будет знать, ждать, пока индикатор активности оживляет. Итак, как я могу заставить приложение начать анимацию сразу после того, как пользователь нажимает «ОК», а предупреждение не будет почернено. Я понимаю? Если вам нужна дополнительная информация, спросите пожалуйста. Спасибо

EDIT: Этот экран имеет фоновый поток, работающий над ним, когда он загружает первый раз за этот день. Перед этим есть экран. На нем у меня есть кнопка продолжения и щелчок, запускающий фоновый поток, который делает то же самое, что и здесь. Я не убиваю его или что-то еще.

EDIT 2:

- (void)refreshDataAction 
    { 
NSLog(@"Refresh Data"); 
self.txtCustomerSearch.text [email protected]""; 
[self cleanUPPreviousLabels]; 

//Put up an alert box indicating user to wait while data is loading. 

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading" 
               message:@"Please wait while data is being refreshed." 
               delegate:self 
             cancelButtonTitle:@"OK" 
             otherButtonTitles:nil, nil]; 
//alert.tag = 10; 
//[alert show]; 
[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:FALSE]; 

NSLog(@"hit in willpresenet alertview at 221"); 
    self.refreshActIndicator.hidden = NO; 
    [self.refreshActIndicator startAnimating]; 
NSLog(@"Dispatching"); 

//Disable the view and all the other controls 
self.txtCustomerSearch.userInteractionEnabled =NO; 
self.txtCustomerSearch.enabled =NO; 
self.btnSearch.enabled =NO; 
self.btnSearch.userInteractionEnabled = NO; 
self.scrollView.userInteractionEnabled = NO; 
//self.view.userInteractionEnabled =NO; 
self.chkButton.enabled = NO; 


[self deletePreviousValues]; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    NSLog(@"Getting customer values"); 
    [self getAllCustomerValues]; 
    NSLog(@"Got customer values"); 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 


    self.txtCustomerSearch.userInteractionEnabled = YES; 
    self.txtCustomerSearch.enabled =YES; 
    self.btnSearch.enabled =YES; 
    self.btnSearch.userInteractionEnabled = YES; 
    self.scrollView.userInteractionEnabled = YES; 
    self.view.userInteractionEnabled =YES; 
    self.chkButton.enabled = YES; 

    [self.refreshActIndicator stopAnimating]; 

    NSLog(@"Saved"); 


}); 
NSLog(@"Dispatched"); 

}

+0

Метод getAllCustomerValues ​​является синхронным или нет? –

+0

@GeorgeSachin. Как мне это узнать? – RookieAppler

+0

@GeorgeSachin. Поскольку он выполняется в очереди async, он будет выполняться асинхронно. – rmaddy

ответ

0

Попробуйте изменить

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
            (unsigned long)NULL), ^(void) { 

на фоне приоритета

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 
            (unsigned long)NULL), ^(void) { 
+0

@ Ric.No. Изменено, но оно все равно похоже на это. Ящик пользователя почернел и через 7-8 секунд он исчезает, а затем начинается моя анимация для индикатора активности. Также я редактировал некоторую информацию в своем первоначальном сообщении. Пожалуйста, проверьте это. – RookieAppler

0

Использование alertView:didDismissWithButtonIndex: вместо alertView:clickedButtonAtIndex:. Таким образом, предупреждение вызывается при вызове кода.

Вопрос - зачем беспокоиться о виде предупреждения? Пользователь знает, что они нажали значок «Обновить». Вы уже указали индикатор активности, и предупреждение не дает пользователю возможность отменить обновление.

Обновление: вызов dispatch_async кажется немного выключенным. Попробуйте это:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self getAllCustomerValues]; 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) { 
     NSLog(@"209 Failed to save second MOC"); 
    } else { 
     //NSLog(@"saved success"); 
    } 
}); 
+0

Ну, когда у меня не было предупреждений, а при нажатии кнопки обновления все же потребовалось 7-8 секунд, чтобы отобразить индикатор активности. Таким образом, экран замер на 7-8 секунд, и ничего не происходит. Нет индикатора. Нет. Я не знаю, почему это занимает то время. Но теперь я представил предупреждение, чтобы сказать им, что что-то происходит. – RookieAppler

+0

То, что вы описали, означает, что загрузка данных ('getAllCustomerValues') действительно работает в основном потоке. Но это не должно быть так, поскольку вы используете этот код в фоновом режиме. См. Мой обновленный ответ. – rmaddy

+0

Я изменил, как вы предлагали. rejectWithButtonIndex и изменение dispatch_async. Но это так. Я нажимаю обновить данные. Открывается окно предупреждения. Нажмите «ОК», чтобы закрыть окно. Оповещение отключено. Задержка 7-8 секунд (ничего не происходит), а затем индикатор начинает вращаться/оживлять. – RookieAppler

0

Это может помочь добавить некоторые NSLogs, чтобы увидеть, где он висит, и остановить индикатор активности, чтобы увидеть, если все зависание происходит из-за отправки.

NSLog(@"hit in clickedbuttonatindex alertview at 259"); 
self.refreshActIndicator.hidden = NO; 
[self.refreshActIndicator startAnimating]; 
NSLog(@"Dispatching"); 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
            (unsigned long)NULL), ^(void) { 
    NSLog(@"Getting customer values"); 
    [self getAllCustomerValues]; 
    NSLog(@"Got customer values"); 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 
    [self.refreshActIndicator stopAnimating]; 
    NSLog(@"Saved"); 
}); 
NSLog(@"Dispatched"); 

Что происходит, что основной (UI) очереди остановки по какой-то причине, что вызывает вещи зависнуть. Поскольку он остановлен, такие вещи, как индикаторы активности обновления, не ожидают, даже если вы сказали им начать анимацию. И помните, что вы не можете обновлять пользовательский интерфейс в async, поэтому secondMOC не следует использовать, чтобы заставить таблицы перезагружать данные и [self getAllCustomerValues]; не должны делать какие-либо элементы интерфейса.

+0

Итак, на симуляторе вывод: нажмите в clickedbuttonatindex alertview на 259.Dispatching.Getting customer values.Dispatched.Got customer values.Saved. Также на симуляторе нет задержки (без ожидания 7-8 секунд). На устройстве требуется время. – RookieAppler

+0

Когда вы отлаживаете устройство - «Запуск на устройстве iOS» - как выглядит вывод? – Ric

+0

Когда я подключаю свое устройство к mac, в xcode я получаю «iPad Phani, iPad 6.1 Simulator, iPhone 6.1 Simulator». Я выбираю «ipad phani», и я запускаю, тогда я не вижу выхода в своем Xcode. О чем ты говоришь? Не могли бы вы немного объяснить. Спасибо – RookieAppler

0

Мы используем MBProgressHUD (https://github.com/jdg/MBProgressHUD), который упрощает такой вид пользовательского интерфейса. Обычно вы предоставляете метод для вызова, который может проверять значение BOOL . BOOL.Установите BOOL, когда вы установите HUD, когда фоновый процесс будет полностью очищен, BOOL и HUD автоматически исчезнут.

0

Вы говорите, что это все происходит на фоне потока - убедитесь, что вы загружаете UIAlertView на главной теме:

//[alert show]; 
[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:FALSE]; 

Это, вероятно, решить эту проблему. Ваш асинхронный вызов на самом деле происходит в текущем потоке цикла выполнения (поскольку это фоновый поток), блокируя отображаемое предупреждение, которое вы пытаетесь отобразить (в том же цикле запуска).

+0

Я отредактировал свой код, как вы сказали. Это не сработало. Я опубликовал здесь обновленный метод refreshDataAction. Взгляните и скажите мне, если вы найдете что-то не так. благодаря – RookieAppler