2010-09-13 29 views
1

J'ai un problème étrange lorsque j'appelle .navigationController popViewControllerAnimated:YES à partir d'un NSOperation où l'écran ne se met pas correctement à jour et laisse la vue éclatée visible mais apparemment désallouée.iPhone/iOS popViewControllerAnimated N'actualise pas l'écran

Détails: Je affichage de la liste qui accède à une base de données sqlite locale. En appuyant sur un enregistrement, il affiche la vue détaillée de cet enregistrement et lance une NSOperation asynchrone (sur le thread principal) pour vérifier la base de données backend XML pour voir si cet enregistrement est toujours disponible dans la base de données. Pour des raisons architecturales, je ne vais pas entrer dans, je ne peux pas exécuter cette opération sur la vue de liste, il doit être dans la vue détaillée. Si l'enregistrement a été supprimé depuis la dernière synchronisation, il informe l'utilisateur que l'enregistrement a été supprimé et appelle le popViewControllerAnimated sur un délégué d'application partagée. Idéalement, cela afficherait la vue détaillée actuelle et retournerait à la liste précédente.

Erreur: La vue est correcte en fait sauté dans la mémoire (il a été désallouée) mais il est toujours affiché à l'écran. La barre de navigation est vide, mais je peux cliquer sur l'endroit où le bouton "retour" devrait être, et il navigue vers l'écran de démarrage avant la vue de liste, ce qui signifie qu'au moins la barre de navigation comprend où elle est supposée être, si ce n'est pas afficher le titre ou les boutons de retour correctement. Le problème principal est que la vue détaillée est toujours visible et peut interagir avec, ce qui provoque le blocage de l'application. Par exemple, la vue détaillée affiche également des données dans un UITableView et si l'utilisateur fait défiler vers le bas dans le tableau, une exception est levée « -[xAccountDetailController tableView:cellForRowAtIndexPath:]: message envoyé à l'instance désalloué »

Cela me porte à croire que le contrôleur de détail a été désallouée correctement par l'appel popViewControllerAnimated, mais évidemment quelque chose réside encore dans la mémoire, si la table appelle en fait le cellForRowAtIndexPath, même si elle est contrôleur de vue a été sauté hors du NavigationController.

pousser manuellement le bouton de retour pendant la vue détaillée (pour un enregistrement qui n'a pas été supprimé à l'arrière) fonctionne parfaitement. Tentatives de contournement: Lorsque je passe à NSOperation une référence au contrôleur de vue détaillée, j'ai tenté d'appeler le popViewControllerAnimated depuis la propriété navigationController de cette vue directement et depuis le délégué de l'application partagée. J'ai également essayé d'afficher deux vues et de repousser la vue de liste sur navigationController mais cela présente un effet d'interface encore plus troublant où les contrôleurs racine et liste semblent exister simultanément dans la barre de navigation (les titres se remplacent) plutôt que d'être inexistant). J'ai essayé de définir la référence au contrôleur de vue de détail qui existe dans le NSOperation à zéro, mais cela ne fait rien. J'ai essayé d'appeler un [detailView release] avant de sauter, mais comme prévu, il échoue sur le pop parce qu'il avait seulement un nombre de retenue de 1 avant la libération. J'ai également essayé popToViewController et popToRootViewController et rien ne semble fonctionner. L'ancienne vue est toujours là, la barre de navigation est le seul élément de l'interface qui semble faire quoi que ce soit et, même dans ce cas, l'affichage est incorrect. J'ai également essayé de recharger la table, car je ne suis pas vraiment dérangé si la vue reste visible (pas de popping), je veux juste effacer les données - mais la table ne rechargera pas Data pour une raison quelconque. Réflexions: Comme la commande operationQueue qui exécute NSOperation est une propriété de la vue détaillée en question, j'ai vérifié que dans la vue détaillée, dealloc annuleAllOperations et que la référence à operationQueue est nulle. J'ai également essayé de m'assurer que toutes les références à cette vue dans d'autres objets ont été mises à zéro. Appel popViewControllerAnimated directement à partir d'un bouton sur la vue détaillée fonctionne parfaitement, il doit donc être le fait que j'appelle cette méthode de la NSOperation, en cours d'exécution sur un NSOperationQueue qui est une propriété de la vue détaillée que je veux pop.Une référence quelque part doit garder cette vue partiellement en vie, mais je n'arrive pas à trouver quelque chose qui fasse toujours référence à la vue quand la pop est appelée.

Il y a trop de code dans trop d'endroits pour en poster ici.

Des pensées?

Désolé pour cette longue question et merci à l'avance,

Greg


Edit 1: je peux reproduire ce problème en dehors du NSOperation avec un nouveau UIViewController facilement.

Dans une méthode tableView:didSelectRowAtIndexPath j'appelle les éléments suivants:

xBaseViewController * vc = [[xBaseViewController alloc] initWithStyle:UITableViewStyleGrouped]; 
[self.navigationController pushViewController:vc animated:YES]; 
[vc performSelectorOnMainThread:@selector(popView) withObject:nil waitUntilDone:YES]; 

En vc, la méthode popView:

[self.navigationController popViewControllerAnimated:YES]; 

Je ne pense pas que cela ait à voir avec conserver compte ou NSOperation. Est-ce que je fais quelque chose de fondamentalement faux en faisant éclater la vue de cette manière?

Répondre

2

Votre problème est que vous essayez d'actualiser l'écran sur un thread qui n'est pas le thread principal. Dans l'iOS, vous pouvez uniquement mettre à jour ce qui se passe à l'écran avec le fil principal.

Vous avez besoin du code comme ceci:

[self performSelectorOnMainThread:@selector(mymethod) withObject:nil waitUntilDone:YES modes:nil]; 

Et il devrait fonctionner dandy.

+0

Merci pour votre réponse. J'ai essayé ceci, mais je n'arrive pas à lancer le sélecteur. En passant par le débogueur, il arrive à cette ligne et saute juste au-dessus. Un point d'arrêt dans la procédure les appels de sélecteur ne sont jamais déclenchés. Changer le nom du sélecteur en quelque chose qui n'existe pas bloque le programme, comme on pouvait s'y attendre, mais avec le bon nom de procédure, il ne l'exécute tout simplement pas. Des idées? G – Greg

+0

Cela a toujours fonctionné pour moi, donc je ne sais pas ce qui ne va pas, peut-être devriez-vous supprimer la partie modes et simplement utiliser 'performSelectorOnMainThread: withObject: waitUntilDone:', mais ce n'est qu'une solution possible, car je ne peux pas savoir que faites-vous exactement dans votre code? –

+0

Merci encore. Laissant de côté les «modes:» travaillés. Mais, malheureusement, cela n'a pas résolu le problème. Le bouton Retour s'anime à droite dans l'oubli, je peux cliquer sur où le nouveau bouton de retour devrait être et il reviendra encore une autre vue en arrière, mais la barre de navigation est vide et la vue désallouée est toujours là. G – Greg