Ce qui est le plus robuste de la force d'une UIView pour redessiner?
J'ai un UITableView avec une liste d'éléments. En sélectionnant un élément pousse un viewController qui procède alors à effectuer les opérations suivantes. à partir de la méthode viewDidLoad j'ai d'incendie à une URLRequest pour les données qui sont requises par une de mes sous-vues - une sous-classe UIView avec drawRect remplacée. Lorsque les données arrivent à partir du nuage, j'ai commencer la construction de mon point de vue de la hiérarchie. la sous-classe en question reçoit les données et la méthode drawRect a maintenant tout ce qu'il faut pour rendre.
Mais.
Parce que je ne l'appelez pas drawRect explicitement - Cacao-Toucher les poignées que je n'ai aucun moyen de les informer de Cacao-Touch que j'ai vraiment, vraiment envie cette sous-classe UIView à rendre. Quand? Maintenant, ce serait bien!!!
J'ai essayé [mavue setNeedsDisplay]. Ce genre de travaux parfois de. Très inégale.
J'ai lutte avec cela pendant des heures et des heures. Quelqu'un qui merci de me fournir un rocher solide, garanti approche à forcer un UIView re-rendre.
Voici l'extrait de code qui se nourrit des données de la vue:
//Create the subview
self.chromosomeBlockView = [[[ChromosomeBlockView alloc] initWithFrame:frame] autorelease];
//Set some properties
self.chromosomeBlockView.sequenceString = self.sequenceString;
self.chromosomeBlockView.nucleotideBases = self.nucleotideLettersDictionary;
//Insert the view in the view hierarchy
[self.containerView addSubview:self.chromosomeBlockView];
[self.containerView bringSubviewToFront:self.chromosomeBlockView];
//A vain attempt to convince Cocoa-Touch that this view is worthy of being displayed ;-)
[self.chromosomeBlockView setNeedsDisplay];
Cheers,
Doug
Vous devez vous connecter pour publier un commentaire.
La garantie, solide comme le roc moyen de forcer un
UIView
à nouveau le rendu est[myView setNeedsDisplay]
. Si vous rencontrez des problèmes avec ça, vous êtes probablement en cours d'exécution dans l'une de ces questions:Vous appelez avant de vous avez réellement les données, ou votre
-drawRect:
est de plus en plus de la mise en cache quelque chose.Vous attendons à la vue de tirer au moment de l'appel de cette méthode. Il est intentionnellement en aucune façon à la demande de "droit de tirage maintenant cette seconde" à l'aide du Cacao en dessinant système de. Susceptibles de perturber la vue d'ensemble système de composition, corbeille de performance et susceptibles de créer toutes sortes de quelques artefacts. Il y a seulement des manières de dire "ce doit être établi, dans le prochain tirage du cycle."
Si ce que vous avez besoin est "un peu de logique, de dessiner, d'autres, plus logique", alors vous avez besoin de mettre le "des plus logique" dans une méthode séparée et d'appeler à l'aide
-performSelector:withObject:afterDelay:
avec un retard de 0. Qui mettez-y un peu plus de logique" après le prochain tirage du cycle. Voir cette question pour un exemple de ce type de code, et un cas où il pourrait être nécessaire (bien qu'il est généralement préférable de chercher d'autres solutions, si possible, car cela complique le code).Si vous ne pensez pas que les choses deviennent tirés, mettre un point d'arrêt dans
-drawRect:
et de voir quand vous êtes appelé. Si vous appelez-setNeedsDisplay
, mais-drawRect:
n'est pas appelé dans la prochaine boucle d'événements, puis creuser dans votre vue de la hiérarchie et assurez-vous que vous n'êtes pas d'essayer de déjouer est quelque part. La sur-l'intelligence est la cause n ° 1 de mauvais dessin dans mon expérience. Quand vous pensez que vous connaissez la meilleure façon de tromper le système en faire ce que vous voulez, vous obtenez généralement il faire exactement ce que vous ne voulez pas.setNeedsDisplay
et de l'appel dedrawRect:
. Tandis que l'appel de la fiabilité est là, je n'appellerais pas cela de la “plus robuste” solution robuste dessin solution devrait, en théorie, faire le dessin immédiatement, avant de retourner au client un code exigeant le tirage au sort.J'ai eu un problème avec un grand délai entre l'appel de setNeedsDisplay et drawRect: (5 secondes). Il s'est avéré que j'ai appelé setNeedsDisplay dans un autre thread que le thread principal. Après le déplacement de cet appel pour le thread principal le retard s'en alla.
Espère que c'est de l'aide.
Le remboursement de la garantie, en béton armé-solide moyen de forcer l'affichage de dessiner de façon synchrone (avant de retourner le code d'appel) est de configurer le
CALayer
s'interactions avec vosUIView
sous-classe.Dans votre sous-classe UIView, créer un
- display
méthode qui indique le calque “oui, il doit afficher”, puis “de faire en sorte”:Également de mettre en œuvre un
- drawLayer:inContext:
méthode qui vais appeler votre privé/interne méthode de dessin (qui fonctionne depuis tous les UIView est un CALayerDelegate):Et de la création de votre propre
- internalDrawWithRect:
méthode, avec fail-safe- drawRect:
:Et maintenant appelez simplement
[myView display]
chaque fois que vous avez vraiment, vraiment besoin de dessiner.- display
de dire leCALayer
àdisplayIfNeeded
, qui de façon synchrone de retour d'appel dans notre- drawLayer:inContext:
et de faire le dessin dans- internalDrawWithRect:
, mise à jour de visual avec ce qui est établi dans le contexte avant de passer.Cette approche est similaire à @RobNapier dessus, mais a l'avantage d'appel
- displayIfNeeded
en plus de- setNeedsDisplay
, ce qui en fait synchrone.Cela est possible parce que
CALayer
s exposer plus de dessins et de fonctionnalités queUIView
s— couches de niveau inférieur que les points de vue et conçu pour le but de hautement configurable dessin dans la mise en page, et (comme beaucoup de choses dans le Cacao) sont conçus pour être utilisés de manière flexible (comme un parent de la classe, ou en tant que délégataire, ou comme un pont à un autre dessin systèmes, ou tout simplement sur leur propre).Plus d'informations sur la configuration de
CALayer
s peuvent être trouvés dans la La configuration d'Objets de la Couche de l'article de la Base de l'Animation Guide de Programmation.drawRect:
explicitement dit "Vous devriez ne jamais appeler cette méthode directement vous-même." Aussi, CALayer dedisplay
explicitement dit "Ne pas appeler cette méthode directement." Si vous voulez dessiner de façon synchrone sur les couchescontents
directement, il n'est pas besoin de violer ces règles. Vous pouvez simplement tirer sur la couche decontents
quand vous le voulez (même sur les threads d'arrière-plan). Il suffit d'ajouter une sous-couche à la vue pour que. Mais c'est différent que de le mettre sur l'écran, qui doit attendre jusqu'à ce que la composition de temps.contents
("Si la couche objet est lié à un objet de vue, vous devriez éviter de fixer le contenu de cette propriété directement. L'interaction entre les vues et les couches habituellement les résultats en vue de remplacer le contenu de cette propriété lors d'une mise à jour ultérieure.") Je ne suis pas particulièrement recommander cette approche; prématuré de dessin mine de la performance et de la qualité des plans. Mais si vous en avez besoin pour une raison quelconque, alorscontents
est de savoir comment l'obtenir.drawRect:
directement. Il n'était pas nécessaire de démontrer cette technique, et a été corrigé.contents
technique, vous êtes suggérant... semble alléchant. J'ai essayé quelque chose comme ça au départ, mais ne pouvais pas le faire fonctionner, et a trouvé la solution ci-dessus pour être beaucoup moins de code avec aucune raison de ne pas être aussi performant. Toutefois, si vous avez une solution de travail pour lacontents
approche, je serais intéressé par la lecture (il n'y a aucune raison pourquoi vous ne pouvez pas avoir deux réponses à cette question, non?)display
. C'est juste une coutume public méthode dans une sous-classe UIView, tout comme ce qui est fait dans GLKView (une autre sous-classe UIView, et la seule Apple-écrit-je sais de qui demande TIRAGE au sort MAINTENANT! fonctionnalité).J'ai eu le même problème, et toutes les solutions à partir de ou Google n'a pas de travail pour moi. Généralement,
setNeedsDisplay
fonctionne, mais quand cela ne fonctionne pas...J'ai essayé d'appeler
setNeedsDisplay
de la vue juste de toutes les manières possibles tous les threads et des trucs - toujours pas de succès. Nous savons, comme l'a dit Rob, quiMais pour quelque raison il ne serait pas tirer de cette époque. Et la seule solution que j'ai trouvé est de l'appeler manuellement après un certain temps, pour laisser quelque chose qui bloque le tirage au sort se passer de loin, comme ceci:
C'est une bonne solution si vous n'avez pas besoin de la vue de redessiner vraiment souvent. Sinon, si vous êtes en train de faire quelque mouvement (action) des choses, il n'y a généralement pas de problème avec juste appeler
setNeedsDisplay
.J'espère que ça va aider quelqu'un qui est perdu, comme je l'étais.
Eh bien, je sais que cela pourrait être un grand changement, ou même ne convient pas à votre projet, mais avez-vous pensé à pas les pousser jusqu'à ce que vous avez déjà les données? De cette façon, vous ne devez dessiner la vue et de l'expérience de l'utilisateur sera également mieux que le poussoir se déplace en est déjà chargé.
La façon dont vous le faire est dans le
UITableView
didSelectRowAtIndexPath
vous de manière asynchrone demander les données. Une fois que vous recevez la réponse, vous effectuez manuellement la séquence et de transmettre les données à votre viewController dansprepareForSegue
.En attendant, vous pouvez montrer certains de l'indicateur d'activité, pour la simple indicateur de chargement de vérifier https://github.com/jdg/MBProgressHUD