Astuces pour améliorer les performances de défilement de l'iPhone UITableView?

89

J'ai un uitableview qui charge des images assez grandes dans chaque cellule et les hauteurs de cellule varient en fonction de la taille de l'image. Les performances de défilement sont correctes, mais peuvent parfois être saccadées.

J'ai trouvé ces conseils que j'ai trouvés sur le blog FieryRobot:

défilement vitreux avec vue modifiable

défilement plus vitreux avec vue modifiable

Quelqu'un at-il des conseils pour améliorer les performances de défilement uitableview?

Jonas
la source
Si vous avez besoin de mettre en cache les hauteurs de cellule (qui peuvent être coûteuses à calculer et sont également utilisées fréquemment), j'ai donné un exemple. Utilisez-le uniquement s'il convient à votre application. stackoverflow.com/questions/1371223/…
Paul de Lange

Réponses:

156
  1. Mettez en cache la hauteur des lignes (la vue de table peut le demander fréquemment)
  2. Créez un cache utilisé le moins récemment pour les images utilisées dans la table (et invalidez toutes les entrées inactives lorsque vous recevez un avertissement de mémoire)
  3. Dessiner tout dans les UITableViewCell« s drawRect:si possible , éviter subviews à tout prix (ou si vous avez besoin de la fonctionnalité d'accessibilité standard, la vue de contenu drawRect:)
  4. Rendre le UITableViewCellcalque de votre opaque (il en va de même pour la vue de contenu si vous en avez une)
  5. Utilisez la fonctionnalité reusableCellIdentifier comme recommandé par les UITableViewexemples / documentation
  6. Évitez les dégradés / effets graphiques compliqués qui ne sont pas précuits en UIImages
rpetrich
la source
5
De plus, les images téléchargées doivent être réduites à la taille de l'imageView avant de s'afficher sur la cellule!
Zoltán Matók
4
Je voudrais ajouter à cette réponse une de mes expériences des dernières années - avoir des cellules transparentes n'est probablement jamais la cause de mauvaises performances de défilement. Nous avons une application avec des cellules TRÈS compliquées (plus de 20 sous-vues) et tout est transparent pour afficher l'arrière-plan. Avec des optimisations appropriées, la transparence ne fait aucune différence, même sur un 3GS. En fait, ce qui ralentissait le plus les choses était le chargement de la pointe avant qu'il n'y ait assez de cellules pour sortir de la vue de la table. Si vous utilisez des sous-vues, assurez-vous simplement d'avoir des hiérarchies efficaces et vous n'avez pas besoin d'utiliser drawRect.
Accatyyc
@Accatyyc, il semble que j'ai le même problème. Il y a un petit décalage lorsqu'il n'y a pas assez de cellules à retirer de la file d'attente, lorsque 3-4 cellules sont retirées de la file d'attente, le défilement est fluide. Existe-t-il un moyen de précharger les cellules afin qu'il y ait des cellules à retirer de la file d'attente et à ne pas charger les fichiers NIB lors du défilement?
Tiois
@Tiois Bien sûr que oui. Vous devez utiliser l'ancienne méthode pour retirer les cellules de la file d'attente (ne pas enregistrer les classes / nibs, mais les créer si dequeueCellWithIdentifier: renvoie nil). De cette façon, vous pouvez créer un ensemble de cellules avant même que votre vue de tableau existe, par exemple en en créant 20 auparavant. Ensuite, au lieu d'en créer de nouveaux dans cellForRowAtIndexPath :, vous les tirez d'abord de votre propre cache, jusqu'à ce qu'il soit vide.
Accatyyc
J'utilise UICollectionView et je suis confronté au même problème. Dans mon fichier de pointe de cellule personnalisé. J'utilise plusieurs sous-vues, y compris UIwebView et UIImageView à l'intérieur d'UIstackView vertical. lorsque je fais défiler ma liste, les cellules réutilisées prennent beaucoup de temps pour réajuster leur taille et le défilement semble très saccadé.
Mansuu ....
40
  1. Si vous faites des sous-classes UITableViewCell, n'utilisez pas de Nib, écrivez-la plutôt dans le code. C'est beaucoup plus rapide que de charger des fichiers Nib.
  2. Si vous utilisez des images, assurez-vous de les mettre en cache afin de ne pas avoir à charger à partir du fichier plus d'une fois pour chacune (si vous avez la mémoire, vous seriez surpris de l'espace occupé par les images).
  3. Rendre autant d'éléments opaques que possible. De même, essayez de ne pas utiliser des images transparentes.
Grenouille poilue
la source
3
ne vous inquiétez pas ... c'étaient des trolls. très bonne réponse!
Steav
79
Les votes à la baisse étaient probablement dus au fait que "éviter les plumes" est un mauvais conseil pour améliorer les performances. Si vous réutilisez des cellules, les cellules ne sont pas du tout reconstruites à partir de pointes lors du défilement.
Steven Fisher le
6
Les pointes sont équivalentes en vitesse, ou un peu plus rapides sur la base de la recherche Cocoa with Love. cocoawithlove.com/2010/03/…
MaxGabriel
@Steven Fisher en utilisant Nib peut être plus lent lorsque la table allocs et les cellules de deallocs, par exemple - pendant le défilement rapide.
Sound Blaster
3
L'utilisation des NIB peut être plus lente lorsque la cellule est en cours de construction . Si vous utilisez le recyclage de cellules, il n'y a que suffisamment de cellules allouées pour remplir l'écran; disons, peut-être 10 au plus. Lorsque vous faites défiler, les cellules ne sont pas créées. Ils sont simplement réutilisés , non désalloués et réaffectés. Et, bien sûr, la désallocation est gratuite. Donc non, ce n'est pas correct.
Steven Fisher
34

Le développeur derrière Tweetie a beaucoup écrit à ce sujet et a du code qui montre comment cela a été fait pour cette application. Fondamentalement, il / elle préconise une vue personnalisée par cellule du tableau, et la dessiner manuellement (plutôt que la sous-visualisation avec Interface Builder, entre autres options).

défilement rapide dans tweetie avec affichage modifiable

En outre, Apple a mis à jour son propre exemple de code pour TableView dans ses didacticiels TableViewSuite (peut-être en réponse à cela?)

TableViewSuite

beno
la source
1
C'est une solution formidable. Je suis juste curieux de savoir comment ajouter un UIButton dans le cellView? Est-il dessiné dans la méthode drawRect?
Sukitha Udugamasooriya
1
@beno, votre lien semble cassé (le premier) une chance de mettre la main sur l'article original?
apouche
3
L'article original peut être lu ici: web.archive.org/web/20100922230053/http://blog.atebits.com/2008/…
jverdi
lien ajouté vers l'archive Web car la version originale n'existe pas
Ralph Willgoss
1

Le tueur n ° 1 des performances pour le défilement UITableView dessine des ombres sur n'importe quel calque de vue de cellule, donc si les performances de défilement sont importantes, ne faites pas d'ombres à moins que cela ne ralentisse votre thread principal.

pensait que cela devait être dit car aucune des réponses acceptées ne faisait mention d'ombres et de couches. : +)

JackyJohnson
la source
6
si les problèmes sont les ombres ajouter ces deux lignes de code et tout fonctionne parfaitement self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Pedro Romão
0

Tout problème de UITableViewperformances de défilement peut être résolu en utilisant des techniques déjà décrites dans d'autres réponses. Cependant, la lenteur des performances est souvent causée par quelque chose de intrinsèquement erroné ou répétitif.

Le fait que UITableViewréutilise les cellules et le fait que chaque cellule peut avoir besoin de sa propre image - ensemble, rend le bit de solution complexe. De la façon dont cela est résolu de manière générale, je résume ici les choses dont il faut s'occuper:

  1. Chargez les données dans la source de données - à partir de REST / base de données. Cette étape doit être effectuée en arrière-plan, en utilisant éventuellement dispatch_async avec la file d'attente GCD.
  2. Créez et initialisez des objets de modèle de données pertinents et placez-les dans un tableau
  3. [tableView reloaddata]
  4. À l'intérieur cellForRowAtIndexPath, incluez le code qui définira les données (texte) à partir de l'objet de modèle de données correct du tableau.
  5. Maintenant, les images peuvent aussi être sous forme d'URL, donc cette étape peut être un peu bizarre en raison de la réutilisation des cellules effectuée par la vue tableau. Le cœur du fait est de charger à nouveau l'image à partir du cache / de l'URL du périphérique à l'aide de la file d'attente asynchrone, puis de la définir pour corriger cell.image (quelle que soit la propriété d'image de votre cellule).

Pour éviter les problèmes, reportez-vous à ce didacticiel sur le chargement différé des images dans la vue tableau.

Nirav Bhatt
la source