UIAlertview suspendu pendant que le thread en arrière-plan charge des données

J'ai un UIBarButtonItem appelé "Actualiser datatables". Lorsque l'user clique dessus, l'application doit actualiser ses données. Ce qui se passe sur ce button, c'est que les services web sont lancés et que datatables XML sont amenées et qu'elles sont de l'ordre de 30000-40000 loggings. Donc, pour empêcher l'IU de se bloquer, j'ai écrit un fil de fond et je l'ai chargé.

- (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"); } }); } 

Comme vous pouvez voir la vue d'alerte apparaît. Je clique sur OK et la boite est toujours là "blackened" et c'est accroché là sur l'écran. Et puis 7-8 secondes plus tard, la boîte disparaît et l'animation commence pour l'indicateur d'activité. Mon but est d'get quelque chose comme ça. 1.User clique sur le button Actualiser datatables. La vue 2.Alert apparaît. 3.User clique sur OK. La boîte 4.Alert disparaît et immédiatement le fil d'arrière-plan commence à fonctionner et je vois l'indicateur d'activité fonctionnant / animant.

L'user saura attendre pendant que l'indicateur d'activité est en cours d'animation. Alors, comment puis-je get l'application pour commencer à animer immédiatement après que l'user clique sur "OK" et l'alerte ne soit pas noirci. Suis-je clair? Si vous avez besoin de plus d'informations, s'il vous plaît requestr. Merci

EDIT: Cet écran a un thread d'arrière-plan qui fonctionne dessus quand il se charge la première fois pour ce jour. Il y a un écran avant ça. Sur celui-ci j'ai continuer le button et le clic qui lance le fil de fond qui fait exactement la même chose comme celui-ci ici. Je ne le tue pas ou n'importe quoi.

EDIT 2:

  - (void)refreshDataAction { NSLog(@"Refresh Data"); self.txtCustomerSearch.text =@""; [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"); 

}

Essayez de changer

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

à la priorité d'arrière-plan

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

Utilisez alertView:didDismissWithButtonIndex: au lieu de alertView:clickedButtonAtIndex: De cette façon, l'alerte est déjà ignorée lorsque votre code est appelé.

Question – pourquoi s'embêter avec la vue d'alerte? L'user sait qu'il a appuyé sur une icône de "rafraîchissement". Vous affichez déjà un indicateur d'activité et l'alerte ne permet pas à l'user d'annuler l'actualisation.

Mise à jour: L'appel à dispatch_async semble un peu éteint. Essaye ça:

 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"); } }); 

Il peut être utile d'append des NSLogs pour voir où ils se trouvent et d'arrêter l'indicateur d'activité pour voir si tout le hang arrive à cause de l'envoi.

  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"); 

Ce qui se passe, c'est que la queue principale (UI) est arrêtée pour une raison quelconque, ce qui fait que les choses semblent se bloquer. Comme il est arrêté, des éléments tels que les indicateurs d'activité de rafraîchissement ne seront pas animés même si vous leur avez demandé de commencer à animer. Et callbackez-vous que vous ne pouvez pas mettre à jour l'interface user en async, donc que secondMOC ne doit pas être utilisé pour que des tables rechargent des données et [self getAllCustomerValues]; ne devrait pas faire d'interface user.

Nous utilisons MBProgressHUD ( https://github.com/jdg/MBProgressHUD ) qui rend ce type de notification d'interface user facile. Généralement, vous fournissez une méthode à appeler qui peut vérifier une valeur BOOL atomique . Réglez le BOOL lorsque vous mettez en place le HUD, lorsque le process d'arrière-plan est terminé, effacez le BOOL et le HUD disparaîtra automatiquement.

Vous dites que tout cela se passe sur un thread d'arrière-plan – assurez-vous de charger le UIAlertView sur le thread principal:

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

Cela va probablement résoudre le problème. Votre appel asynchronous se passe réellement sur le thread en cours dans la boucle d'exécution (puisqu'il s'agit d'un thread d'arrière-plan), bloquant la vue d'alerte que vous essayez d'afficher (dans la même boucle d'exécution).