1

Contexte:Quelle est la meilleure pratique pour une opération de longue durée qui met à jour les données dans une tablevue iphone en cours d'affichage?

J'ai un tableview afficher environ 8 sections, chacune soutenue avec ma propre classe PlaceList représentant une liste d'objets (la mise en œuvre utilise un NSMutableArray). Il y a environ 200 objets au total. Chaque section correspond à la distance de l'objet par rapport à l'emplacement actuel (par exemple, à moins de 1 mile, à 10, 25, 50, etc. ...). De temps en temps, j'ai besoin de répondre à des notifications asynchrones de CoreLocation qui me demandent de recalculer la section à laquelle appartient chaque objet, de mettre à jour la distance pour chaque objet (qui est affiché dans chaque cellule) et d'utiliser chaque liste , puis rechargez la vue de la table. Je fais aussi cette opération dans viewWillAppear.

Dans l'opération qui effectue la mise à jour (une méthode sur PlaceList) j'ai utilisé @synchronized (self) au cas où elle serait invoquée par plus d'un thread par le système d'exploitation (je n'utilise pas un autre thread maintenant). Cependant, cette opération a pour résultat que l'interface utilisateur se bloque de temps en temps, donc je cherche des façons de le faire dans son propre fil.

Question:

  • Quelle est la meilleure façon de faire ce genre de longue opération en cours d'exécution sur les données soutenant une vue de table? Autant que je puisse voir, il n'est pas sûr de faire tourner un thread d'arrière-plan pour faire l'opération, car même si j'utilise performSelector pour recharger la vue du tableau sur le thread principal, il est toujours possible que l'utilisateur appuie sur une cellule lorsque l'opération est en cours et que les données ne sont pas cohérentes avec l'affichage. Et l'ajout de toute sorte de verrouillage ne ferait que vaincre le but. L'interface utilisateur et le gestionnaire de localisation CoreLocation envoient-ils leurs notifications sur le même thread, c'est-à-dire que je peux me passer du @synchronized (self) de la placelist?

Répondre

3

Voici ma compréhension de votre problème. Vous avez une grande liste de données, et à un moment donné, cela deviendra invalide. Afin de le rendre à nouveau valide, vous devez effectuer un traitement avant de pouvoir repeindre la table.

Si cela est correct, voici quelques options.

1) Double buffer vos données. Tant que vous affichez quelque chose qui "était" correct, l'utilisateur peut très bien interagir avec lui. Lorsque vous obtenez votre déclencheur pour retraiter vos données, travaillez dessus en arrière-plan avec une copie, et quand il est prêt à redessiner complètement, mettez à jour. Cette mise à jour peut être abrupte et importante, mais les données affichées seront toujours correctes, ou au moins saines, et l'interface utilisateur continue à fonctionner et n'effraie pas l'utilisateur.

Cela évite en grande partie le problème de thread car les notifications ne modifient pas les données et tentent de les afficher en même temps. Autant que je sache, l'application Facebook semble faire cela, ainsi que TwitterFon. Au moins c'est comme ça. Difficile à dire à coup sûr.

2) Chargement de l'écran! Pas drôle, mais ça marche. Lorsque vous savez que les données sont mauvaises, lancez un panneau semi-transparent et dites à l'utilisateur de patienter un peu.

Il se résume vraiment à mettre à jour maintenant, ou plus tard. Vous devez décider quels compromis ont le plus de sens dans votre demande.

+0

Avoir essayé l'option d'écran de chargement, mais je pense que je vais donner l'option 1 a aller, peut-être en utilisant un NSOperationQueue pour démarrer la mise à jour sur un thread de travail. L'inconvénient est que la mise à jour est potentiellement très volumineuse de temps en temps (c'est-à-dire que les choses se déplacent entre les sections), ce qui pourrait être bizarre pour l'utilisateur. Je me demande si tableview peut être fait animer ça. – frankodwyer