74 votes

iOS: utilisation du 'drawRect:' d'UIView par rapport à la délagation de son calque 'drawLayer: inContext:'

J'ai une classe qui est une sous-classe de UIView. Je suis capable de dessiner des choses à l'intérieur de la vue, soit par la mise en œuvre de l' drawRect méthode, ou par la mise en œuvre de drawLayer:inContext: qui est un délégué de la méthode de CALayer.

J'ai deux questions:

  1. Comment décider de l'approche à utiliser? Est-il un cas d'utilisation pour chacun?
  2. Si j'implémente drawLayer:inContext:, il est appelé (et drawRect n'est pas, au moins autant que de mettre un point d'arrêt peut dire), même si je n'ai pas affecter mon point de vue de l' CALayer délégué à l'aide de:

    [[self layer] setDelegate:self];

    comment se fait-le délégué méthode est appelée si mon exemple n'est pas défini à la couche du délégué? et quel est le mécanisme qui empêche drawRect d'être appelé si drawLayer:inContext: est appelé?

71voto

Nathan Eror Points 6713

Comment décider de l'approche à utiliser? Est-il un cas d'utilisation pour chacun?

Toujours utiliser drawRect:, et n'utilisez jamais une UIView comme le dessin délégué pour n'importe quel CALayer.

comment se fait-le délégué méthode est appelée si mon exemple n'est pas défini à la couche du délégué? et quel est le mécanisme qui empêche drawRect d'être appelé si drawLayer:inContext: est appelé?

Chaque UIView exemple est le dessin délégué pour son soutien CALayer. C'est pourquoi, [[self layer] setDelegate:self]; semblait ne rien faire. C'est redondant. L' drawRect: méthode est effectivement le dessin délégué pour la méthode de vue de la couche. En interne, UIView implémente drawLayer:inContext: où il n'certains de ses propres trucs et puis les appels drawRect:. Vous pouvez le voir dans le débogueur:

drawRect: stacktrace

C'est pourquoi, drawRect: n'a jamais été appelée lorsque vous avez mis en œuvre drawLayer:inContext:. C'est aussi pourquoi vous devriez ne jamais les mettre en œuvre de l' CALayer dessin délégué méthodes dans une coutume UIView sous-classe. Vous devez également ne jamais faire d'afficher le dessin délégué pour une autre couche. Qui provoque toutes sortes de délires.

Si vous êtes à la mise en œuvre de drawLayer:inContext: parce que vous avez besoin pour accéder à l' CGContextRef, vous pouvez obtenir à partir de l'intérieur de votre drawRect: en appelant UIGraphicsGetCurrentContext().

45voto

quellish Points 5475

drawRect devrait être mis en œuvre que lorsque c'est absolument nécessaire. L'implémentation par défaut de drawRect comprend un certain nombre de smart optimisations, comme intelligemment mise en cache de la vue du rendu. Remplaçant contourne toutes ces optimisations. C'est un mauvais. À l'aide de la couche de dessin efficace des méthodes sera presque toujours plus personnalisée drawRect. Apple utilise un UIView en tant que délégué pour un CALayer souvent - en fait, chaque UIView est le délégué de la couche. Vous pouvez voir comment personnaliser la couche de dessin à l'intérieur d'une UIView dans plusieurs Apple échantillons, y compris (en ce moment) ZoomingPDFViewer.

Alors que l'utilisation d' drawRect est commun, c'est une pratique qui a été découragé, au moins depuis 2002/2003, IIRC. Il n'y a pas beaucoup de bonnes raisons de gauche pour aller dans cette voie.

Avancées d'Optimisation de la Performance de l'iPhone OS (diapo 15)

Core Animation Essentials

La Compréhension De UIKit Rendu

Technique Q&A QA1708: Amélioration de l'Image Performance de Dessin sur iOS

Afficher Guide De Programmation: Optimisation De Vue De Dessin

13voto

Dennis Fan Points 81

Voici les codes de l'exemple ZoomingPDFViewer d'Apple:

 -(void)drawRect:(CGRect)r
{

    // UIView uses the existence of -drawRect: to determine if it should allow its CALayer
    // to be invalidated, which would then lead to the layer creating a backing store and
    // -drawLayer:inContext: being called.
    // By implementing an empty -drawRect: method, we allow UIKit to continue to implement
    // this logic, while doing our real drawing work inside of -drawLayer:inContext:

}

-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context
{
    ...
}
 

7voto

Ole Begemann Points 85798

Sur iOS, le chevauchement entre la vue et le son de la couche est très grand. Par défaut, la vue est le délégué de sa couche et met en œuvre la couche en drawLayer:inContext: méthode. Comme je le comprends, drawRect: et drawLayer:inContext: sont plus ou moins équivalentes dans ce cas. Éventuellement, l'implémentation par défaut de drawLayer:inContext: des appels drawRect:ou drawRect: n'est appelée que si drawLayer:inContext: n'est pas mis en œuvre par votre sous-classe.

Comment décider de l'approche à utiliser? Est-il un cas d'utilisation pour chacun?

Il n'a pas vraiment d'importance. Pour suivre la convention, je voudrais l'utiliser normalement drawRect: et réserver l'utilisation de l' drawLayer:inContext: quand je dois dessiner personnalisé des sous-couches qui ne font pas partie de la vue.

2voto

jamie Points 1450

La Documentation d'Apple a ceci à dire: "Il y a aussi d'autres moyens pour fournir une vue du contenu, telles que la définition du contenu de la couche sous-jacente directement, mais en remplaçant la drawRect: la méthode est la technique la plus courante."

Mais il ne veut pas aller dans les détails, de sorte que devrait être un indice: ne pas le faire, sauf si vous voulez vraiment obtenir vos mains sales.

Le UIView de la couche de son délégué a souligné les UIView. Cependant, la UIView ne se comportent différemment selon si oui ou non drawRect: est mis en œuvre. Par exemple, si vous définissez les propriétés de la couche directement (comme la couleur d'arrière-plan ou de son rayon d'angle), ces valeurs sont écrasées si vous avez un drawRect: méthode - même complètement vide (c'est à dire ne marche pas même appeler super).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X