Apple a défini assez clairement comment sous-classer UIView
dans la doc.
Consultez la liste ci-dessous, en particulier jetez un œil à initWithFrame:
et layoutSubviews
. Le premier est destiné à configurer le cadre de votre UIView
alors que le second est destiné à configurer le cadre et la disposition de ses sous-vues.
Souvenez-vous également qu'il initWithFrame:
n'est appelé que si vous instanciez votre UIView
programme par programme. Si vous le chargez à partir d'un fichier nib (ou d'un storyboard), initWithCoder:
sera utilisé. Et dans initWithCoder:
le cadre n'a pas encore été calculé, vous ne pouvez donc pas modifier le cadre que vous avez configuré dans Interface Builder. Comme suggéré dans cette réponse, vous pouvez penser à appeler initWithFrame:
depuis initWithCoder:
pour configurer la trame.
Enfin, si vous chargez votre à UIView
partir d'une pointe (ou d'un storyboard), vous avez également la awakeFromNib
possibilité d'effectuer des initialisations personnalisées de cadre et de mise en page, car quand il awakeFromNib
est appelé, il est garanti que chaque vue de la hiérarchie a été désarchivée et initialisée.
Extrait du doc de NSNibAwaking
(maintenant remplacé par le doc de awakeFromNib
):
Les messages à d'autres objets peuvent être envoyés en toute sécurité à partir de awakeFromNib - à ce moment, il est assuré que tous les objets sont désarchivés et initialisés (mais pas nécessairement réveillés, bien sûr)
Il est également intéressant de noter qu'avec la mise en page automatique, vous ne devez pas définir explicitement le cadre de votre vue. Au lieu de cela, vous êtes censé spécifier un ensemble de contraintes suffisantes pour que le cadre soit automatiquement calculé par le moteur de mise en page.
Directement à partir de la documentation :
Méthodes de remplacement
Initialisation
initWithFrame:
Il est recommandé de mettre en œuvre cette méthode. Vous pouvez également implémenter des méthodes d'initialisation personnalisées en plus ou à la place de cette méthode.
initWithCoder:
Implémentez cette méthode si vous chargez votre vue à partir d'un fichier nib Interface Builder et que votre vue nécessite une initialisation personnalisée.
layerClass
Implémentez cette méthode uniquement si vous souhaitez que votre vue utilise une couche Core Animation différente pour son magasin de stockage. Par exemple, si vous utilisez OpenGL ES pour faire votre dessin, vous voudrez remplacer cette méthode et renvoyer la classe CAEAGLLayer.
Dessin et impression
drawRect:
Implémentez cette méthode si votre vue dessine un contenu personnalisé. Si votre vue ne fait aucun dessin personnalisé, évitez de remplacer cette méthode.
drawRect:forViewPrintFormatter:
N'implémentez cette méthode que si vous souhaitez dessiner le contenu de votre vue différemment lors de l'impression.
Contraintes
requiresConstraintBasedLayout
Implémentez cette méthode de classe si votre classe de vue nécessite des contraintes pour fonctionner correctement.
updateConstraints
Implémentez cette méthode si votre vue doit créer des contraintes personnalisées entre vos sous-vues.
alignmentRectForFrame:
, frameForAlignmentRect:
Implémentez ces méthodes pour remplacer la façon dont vos vues sont alignées sur d'autres vues.
Disposition
sizeThatFits:
Implémentez cette méthode si vous souhaitez que votre vue ait une taille par défaut différente de celle qu'elle aurait normalement lors des opérations de redimensionnement. Par exemple, vous pouvez utiliser cette méthode pour empêcher votre vue de se réduire au point où les sous-vues ne peuvent pas être affichées correctement.
layoutSubviews
Implémentez cette méthode si vous avez besoin d'un contrôle plus précis sur la mise en page de vos sous-vues que ne le fournissent les comportements de contrainte ou de redimensionnement automatique.
didAddSubview:
, willRemoveSubview:
Implémentez ces méthodes si nécessaire pour suivre les ajouts et les suppressions de sous-vues.
willMoveToSuperview:
, didMoveToSuperview
Implémentez ces méthodes si nécessaire pour suivre le mouvement de la vue actuelle dans votre hiérarchie de vues.
willMoveToWindow:
, didMoveToWindow
Implémentez ces méthodes si nécessaire pour suivre le mouvement de votre vue vers une autre fenêtre.
Gestion des événements:
touchesBegan:withEvent:
, touchesMoved:withEvent:
, touchesEnded:withEvent:
, touchesCancelled:withEvent:
Mettre en œuvre ces méthodes si vous avez besoin pour gérer les événements tactiles directement. (Pour la saisie basée sur les gestes, utilisez des outils de reconnaissance de gestes.)
gestureRecognizerShouldBegin:
Implémentez cette méthode si votre vue gère directement les événements tactiles et peut vouloir empêcher les outils de reconnaissance de gestes attachés de déclencher des actions supplémentaires.
Gabriele Petronella
la source
layoutSubviews
?Cela revient toujours haut dans Google. Voici un exemple mis à jour pour swift.
La
didLoad
fonction vous permet de mettre tout votre code d'initialisation personnalisé. Comme d'autres l'ont mentionné,didLoad
sera appelé lorsqu'une vue est créée par programme viainit(frame:)
ou lorsque le désérialiseur XIB fusionne un modèle XIB dans votre vue viainit(coder:)
la source
draw
méthode?Il y a un résumé correct dans la documentation Apple , et cela est bien couvert dans le cours gratuit de Stanford disponible sur iTunes. Je présente ma version TL; DR ici:
Si votre classe se compose principalement de sous-vues, le bon endroit pour les allouer est dans les
init
méthodes. Pour les vues, il existe deuxinit
méthodes différentes qui peuvent être appelées, selon que votre vue est instanciée à partir du code ou d'une pointe / storyboard. Ce que je fais, c'est d'écrire ma propresetup
méthode, puis de l'appeler à partir des méthodesinitWithFrame:
etinitWithCoder:
.Si vous effectuez un dessin personnalisé, vous souhaitez en effet remplacer
drawRect:
dans votre vue. Si votre vue personnalisée est principalement un conteneur pour les sous-vues, vous n'aurez probablement pas besoin de le faire.Ne remplacez que
layoutSubViews
si vous voulez faire quelque chose comme ajouter ou supprimer une sous-vue selon que vous êtes en orientation portrait ou paysage. Sinon, vous devriez pouvoir le laisser tranquille.la source
layoutSubViews
, cela a fonctionné.layoutSubviews
est destiné à définir le cadre sur les vues enfants, pas sur la vue elle-même.Pour
UIView
, le constructeur désigné est généralementinitWithFrame:(CGRect)frame
et vous devez définir le cadre ici (ou dansinitWithCoder:
), en ignorant éventuellement la valeur du cadre. Vous pouvez également fournir un constructeur différent et y définir le cadre.la source
awakeFromNib