Pour clarifier le but de cette question: Je sais COMMENT créer des vues compliquées avec les deux sous-vues et en utilisant drawRect. J'essaie de bien comprendre le quand et le pourquoi d'utiliser l'un sur l'autre.
Je comprends également qu'il n'est pas logique d'optimiser autant à l'avance et de faire quelque chose de plus difficile avant de faire un profilage. Considérez que je suis à l'aise avec les deux méthodes et que maintenant je veux vraiment une compréhension plus profonde.
Une grande partie de ma confusion vient de l'apprentissage de la façon de rendre les performances de défilement des vues de table vraiment fluides et rapides. Bien sûr, la source originale de cette méthode provient de l' auteur derrière Twitter pour iPhone (anciennement tweetie). Fondamentalement, cela dit que pour rendre le défilement du tableau fluide, le secret est de NE PAS utiliser de sous-vues, mais de faire tout le dessin dans une seule vue personnalisée. Essentiellement, il semble que l'utilisation de nombreuses sous-vues ralentit le rendu car elles ont beaucoup de surcharge et sont constamment recomposées sur leurs vues parentes.
Pour être honnête, cela a été écrit lorsque le 3GS était assez nouveau et que les iDevices sont devenus beaucoup plus rapides depuis. Pourtant cette méthode est régulièrement suggérée sur les interwebs et ailleurs pour les tables hautes performances. En fait, c'est une méthode suggérée dans l'exemple de code de table d'Apple , a été suggérée dans plusieurs vidéos de la WWDC ( Practical Drawing for iOS Developers ) et dans de nombreux livres de programmation iOS .
Il existe même des outils géniaux pour concevoir des graphiques et générer du code Core Graphics pour eux.
Donc, au début, je suis amené à croire "il y a une raison pour laquelle Core Graphics existe. C'est RAPIDE!"
Mais dès que je pense avoir l'idée "Favoriser les graphiques de base lorsque c'est possible", je commence à voir que drawRect est souvent responsable d'une mauvaise réactivité dans une application, est extrêmement coûteux en termes de mémoire et impose vraiment le CPU. Fondamentalement, je devrais " éviter de surcharger drawRect " ( Performance de l'application iOS WWDC 2012 : graphiques et animations )
Donc je suppose que, comme tout, c'est compliqué. Peut-être que vous pouvez m'aider moi-même et aider les autres à comprendre quand et pourquoi utiliser drawRect?
Je vois quelques situations évidentes pour utiliser Core Graphics:
- Vous avez des données dynamiques (exemple de graphique boursier d'Apple)
- Vous avez un élément d'interface utilisateur flexible qui ne peut pas être exécuté avec une simple image redimensionnable
- Vous créez un graphique dynamique qui, une fois rendu, est utilisé à plusieurs endroits
Je vois des situations pour éviter les graphiques de base:
- Les propriétés de votre vue doivent être animées séparément
- Vous avez une hiérarchie de vues relativement petite, donc tout effort supplémentaire perçu en utilisant CG ne vaut pas le gain
- Vous souhaitez mettre à jour des éléments de la vue sans redessiner le tout
- La mise en page de vos sous-vues doit être mise à jour lorsque la taille de la vue parent change
Alors donnez vos connaissances. Dans quelles situations atteignez-vous pour drawRect / Core Graphics (qui pourrait également être accompli avec des sous-vues)? Quels facteurs vous ont conduit à cette décision? Comment / pourquoi le dessin dans une vue personnalisée est-il recommandé pour un défilement fluide des cellules de tableau, alors qu'Apple déconseille drawRect pour des raisons de performances en général? Qu'en est-il des images d'arrière-plan simples (quand les créez-vous avec CG vs en utilisant une image png redimensionnable)?
Une compréhension approfondie de ce sujet n'est peut-être pas nécessaire pour créer des applications intéressantes, mais je n'aime pas choisir entre les techniques sans pouvoir expliquer pourquoi. Mon cerveau se fâche contre moi.
Mise à jour de la question
Merci pour l'information à tous. Quelques questions de clarification ici:
- Si vous dessinez quelque chose avec des graphiques de base, mais que vous pouvez accomplir la même chose avec UIImageViews et un png pré-rendu, devriez-vous toujours emprunter cette voie?
- Une question similaire: Surtout avec des outils badass comme celui-ci , quand devriez-vous envisager de dessiner des éléments d'interface dans les graphiques de base? (Probablement lorsque l'affichage de votre élément est variable. Par exemple, un bouton avec 20 variations de couleurs différentes. D'autres cas?)
- Compte tenu de ma compréhension dans ma réponse ci-dessous, les mêmes gains de performances pour une cellule de tableau pourraient-ils être obtenus en capturant efficacement un instantané bitmap de votre cellule après le rendu UIView complexe lui-même, et en l'affichant tout en faisant défiler et en masquant votre vue complexe? De toute évidence, certaines pièces devraient être élaborées. Juste une pensée intéressante que j'avais.
la source
Je vais essayer de garder un résumé de ce que j'extrapole à partir des réponses des autres ici, et poser des questions de clarification dans une mise à jour de la question d'origine. Mais j'encourage les autres à continuer de répondre et à voter pour ceux qui ont fourni de bonnes informations.
Approche générale
Il est tout à fait clair que l'approche générale, comme Ben Sandofsky l'a mentionné dans sa réponse , devrait être "Chaque fois que vous le pouvez, utilisez UIKit. Faites l'implémentation la plus simple qui fonctionne. Profil. Quand il y a une incitation, optimisez."
Le pourquoi
Dessiner le contenu des cellules dans un UIView plat peut considérablement améliorer votre FPS sur les tableaux défilants.
Comme je l'ai dit ci-dessus, le CPU et le GPU sont deux goulots d'étranglement possibles. Comme ils gèrent généralement des choses différentes, vous devez faire attention à quel goulot d'étranglement vous vous heurtez. Dans le cas des tableaux de défilement, ce n'est pas que Core Graphics dessine plus rapidement, et c'est pourquoi il peut grandement améliorer votre FPS.
En fait, Core Graphics peut très bien être plus lent qu'une hiérarchie UIView imbriquée pour le rendu initial. Cependant, il semble que la raison typique du défilement saccadé soit que vous goulotez le GPU, vous devez donc résoudre ce problème.
Pourquoi le remplacement de drawRect (à l'aide de graphiques de base) peut aider le défilement du tableau:
D'après ce que je comprends, le GPU n'est pas responsable du rendu initial des vues, mais se voit remettre des textures, ou des bitmaps, parfois avec certaines propriétés de calque, après leur rendu. Il est alors responsable de la composition des bitmaps, du rendu de tous ces effets de calque et de la majorité de l'animation (Core Animation).
Dans le cas des cellules de vue de tableau, le GPU peut être goulot d'étranglement avec des hiérarchies de vues complexes, car au lieu d'animer un bitmap, il anime la vue parente, effectue des calculs de disposition de sous-vue, rend les effets de calque et compose toutes les sous-vues. Ainsi, au lieu d'animer un bitmap, il est responsable de la relation d'un groupe de bitmaps, et de la façon dont ils interagissent, pour la même zone de pixels.
Donc, en résumé, la raison pour laquelle dessiner votre cellule dans une vue avec des graphiques de base peut accélérer le défilement de votre tableau n'est PAS parce qu'elle dessine plus rapidement, mais parce que cela réduit la charge sur le GPU, ce qui est le goulot d'étranglement qui vous pose problème dans ce scénario particulier. .
la source
Je suis un développeur de jeux et je posais les mêmes questions quand mon ami m'a dit que ma hiérarchie de vues basée sur UIImageView allait ralentir mon jeu et le rendre terrible. J'ai ensuite recherché tout ce que je pouvais trouver pour savoir s'il fallait utiliser UIViews, CoreGraphics, OpenGL ou quelque chose de tiers comme Cocos2D. La réponse constante que j'ai obtenue d'amis, d'enseignants et d'ingénieurs Apple à la WWDC était qu'il n'y aura pas beaucoup de différence à la fin parce qu'à un certain niveau, ils font tous la même chose . Les options de niveau supérieur telles que UIViews reposent sur les options de niveau inférieur telles que CoreGraphics et OpenGL, mais elles sont simplement enveloppées dans du code pour vous faciliter l'utilisation.
N'utilisez pas CoreGraphics si vous allez simplement réécrire l'UIView. Cependant, vous pouvez gagner de la vitesse en utilisant CoreGraphics, à condition de faire tout votre dessin dans une seule vue, mais cela en vaut- il vraiment la peine ? La réponse que j'ai trouvée est généralement non. Quand j'ai commencé mon jeu, je travaillais avec l'iPhone 3G. Au fur et à mesure que mon jeu devenait de plus en plus complexe, j'ai commencé à voir un certain décalage, mais avec les nouveaux appareils, c'était complètement imperceptible. Maintenant, j'ai beaucoup d'action en cours, et le seul décalage semble être une baisse de 1 à 3 fps lorsque vous jouez au niveau le plus complexe sur un iPhone 4.
J'ai quand même décidé d'utiliser Instruments pour trouver les fonctions qui prenaient le plus de temps. J'ai trouvé que les problèmes n'étaient pas liés à mon utilisation d'UIViews . Au lieu de cela, il appelait à plusieurs reprises CGRectMake pour certains calculs de détection de collision et chargeait les fichiers image et audio séparément pour certaines classes qui utilisent les mêmes images, plutôt que de les faire tirer d'une classe de stockage centrale.
Donc, en fin de compte, vous pourrez peut-être obtenir un léger gain en utilisant CoreGraphics, mais généralement cela ne vaut pas la peine ou peut ne pas avoir d'effet du tout. La seule fois où j'utilise CoreGraphics, c'est lorsque je dessine des formes géométriques plutôt que du texte et des images.
la source