Je suis kyoya, stagiaire dans une entreprise auto-développée. Étant donné que ma connaissance du cycle de mise en page de ViewController et UIView était gâchée en moi, j'ai décidé de l'organiser en moi-même et de la résumer avec le sens de l'explication pour les débutants.
Étonnamment, beaucoup de gens pensent que ViewController et View sont confondus, alors organisons-les une fois ici.
Ce contrôleur de vue, qui est généré lorsque vous lancez un projet avec Xcode, est comme vous si vous êtes débutant. Ce n'est pas grave si vous pensez que ce contrôleur de vue gère l'affichage de la vue d'une manière très simple. Et une vue est associée à un contrôleur de vue. Lors de la création d'un écran, placez des boutons et des étiquettes sur cet UIView lié. (Lorsque deux vues se chevauchent, la vue de la hiérarchie inférieure est appelée vue parente (Super View) et la vue de la hiérarchie supérieure est appelée vue enfant (Vue secondaire))
J'expliquerai le cycle de vie, qui fait également l'objet de cet article. Le cycle de vie est un ensemble de processus permettant d'afficher l'écran. Par exemple, divers processus tels que la lecture du contrôleur de vue en mémoire, le calcul des informations de position de la vue à afficher et l'affichage réel de la vue à l'écran. Est en cours d'exécution. Et comme je l'ai dit, il existe deux types de traitement dans le cycle de vie: le traitement du côté du contrôleur de vue et le traitement du côté de la vue. Il y a un moment pour afficher la vue dans le ViewController, mais il est normal de comprendre que le traitement du côté de la vue y est effectué.
Je vais vous expliquer le traitement du cycle de vie du contrôleur de vue. À partir de la conclusion, le processus se déroulera comme l'image ci-dessous.
En disant que vous êtes arrivé à cet article, vous avez probablement vu des images comme celle-ci plusieurs fois. Et à chaque fois, certaines personnes peuvent penser qu'elles ne peuvent pas se souvenir ou comprendre. Ça va. Je vais l'expliquer d'une manière facile à comprendre.
Tout d'abord, le cycle de vie du contrôleur de vue peut être grossièrement divisé en trois étapes. (ViewWillDissappear et viewDidDisappear au moment de la transition de vue sont omis) Charger ViewController → Afficher la vue de ViewController → Une fois l'affichage terminé Regardons chacun d'eux
Tout d'abord, enregistrez le contrôleur de vue correspondant à l'écran à afficher dans la mémoire (comme une zone de données). Après l'enregistrement, même si vous effectuez une transition d'écran, elle ne disparaîtra pas de la mémoire, elle ne sera donc appelée qu'au premier affichage. Les deux méthodes suivantes sont appelées ici.
loadView()
viewDidLoad()
viewWillAppear()
loadView () '' est le processus d'enregistrement réel du contrôleur de vue en mémoire.
viewDidLoad () '' est un processus qui est appelé après l'enregistrement en mémoire. LoadView () '' a fini de charger le contrôleur de vue, et le chargement de la vue maintenue est également
loadView () ''. Puisqu'il se termine par , dans
viewDidLoad () '', vous pouvez définir les propriétés de chaque vue (paramètre de couleur d'arrière-plan, paramètre de texte d'étiquette, etc.) comme indiqué ci-dessous.
override func viewDidLoad() {
super.viewDidLoad()
testView.backgroundColor = .red
}
viewWillAppear () '' est appelé avant d'afficher l'image. Ceci est également appelé lors du changement de TabBars, comme il est appelé à chaque fois que l'écran est affiché. Contrairement à
viewDidLoad () '', il se caractérise par le fait qu'il est appelé plusieurs fois.
Après avoir lu dans la mémoire et défini les propriétés de chaque vue, la vue s'affichera ensuite. Les deux méthodes suivantes sont appelées ici.
viewWillLayoutSubViews()
viewDidLayoutSubViews()
viewWillLayoutSubVIews () '' est appelé avant le début de la mise en page View. Il est également appelé lorsque l'écran pivote, lorsque la taille de la vue est modifiée ou lorsque la vue est supprimée ou ajoutée. Et après cela, nous entrerons dans la mise en page de View (décrite plus tard)
viewDidLayoutSubViews () '' est appelé une fois la disposition de la vue terminée. Donc, ici, la disposition de la vue est terminée, et la position et la taille de la vue sont décidées.
La méthode suivante est appelée ici.
viewDidAppear()
viewDidAppear () '' est appelé une fois l'affichage de l'écran terminé. Donc, le processus que vous ajoutez ici est fondamentalement sans rapport avec l'expérience utilisateur. Par exemple, afficher les journaux. De plus, puisque cette méthode est associée à
viewWillAppear () '', elle est également appelée à chaque fois que l'écran est affiché.
C'est l'explication du cycle de vie du contrôleur de vue lui-même.
À partir de là, nous passerons au cycle de vie de la vue. Ce processus est appelé après le précédent `` viewWillLayoutSubViews () ''. Le cycle de vie de la vue est affiché à travers le processus suivant. Mise à jour des contraintes → Mise à jour des informations du cadre → Rendu (processus de dessin) Regardons chacun d'eux
Le processus de mise à jour de la contrainte est exécuté lorsque la contrainte change. Le processus qui provoque le changement de contrainte est le suivant.
-Ajouter ou supprimer des contraintes ・ Changer la priorité des contraintes -Changer la hiérarchie de la vue contrainte
Ainsi, lorsque vous exécutez `` NSLayoutConstraints.activate ([~~~]) '', updateConstrains () sera appelé.
Lorsque le processus de mise à jour de la contrainte est exécuté, la fonction «updateConstraints ()» de la vue qui a la contrainte est appelée. Soyez prudent ici. Vous pourriez penser à «updateConstraints ()» comme mélangé avec la méthode de ViewController, mais comme le ViewController lui-même ne peut pas être contraint, cette méthode est la propre méthode de View. (Ce que View a signifie qu'il a également UIButton et UILabel qui héritent de la classe UIView).
Il est également possible d'appeler le processus de mise à jour des contraintes à tout moment. Vous pouvez appeler ʻupdateConstraints ()
ʻune vue qui nécessite des mises à jour de contraintes en appelant` ʻupdateConstraintsIfNeeded () . Vous pouvez également marquer la vue comme "mise à jour de contrainte requise" en appelant
setNeedsUpdateCOnstrains () ''.
C'est compliqué, mais comme ʻupdateConstrainsIfNeeded ()
applique le traitement de mise à jour de contrainte à sa propre vue et à sa sous-vue, par exemple, même si vous exécutez ʻupdateConstrainsIfNeeded ()
sur une certaine vue, son parent Même si l'indicateur de mise à jour de la contrainte est défini dans View, aucun traitement n'est effectué.
C'est un peu compliqué, donc pour résumer, appeler ʻupdateConstrainsIfNeeded ()
appelle ʻupdateConstrains ()
de la vue qui a appelé `` setNeedsUpdateConstrains () '' dans sa propre vue et sa sous-vue. ..
De plus, vous pouvez également mettre à jour la contrainte que `` setNeedsUpdateConstrains () '' a été appelée au moment de la prochaine mise à jour de la contrainte (le timing est laissé au système, mais celui-ci est recommandé * la raison sera décrite plus tard)
J'espère que vous pouvez considérer les informations du cadre comme des informations telles que la position et la taille de la vue. Ce processus est appelé lorsque les informations de trame sont mises à jour. Les déclencheurs à appeler sont les suivants.
-Changer le cadre de vue
-Lorsqu'une vue est ajoutée ou supprimée
・ (En prime) Lorsque le contentOffSet
du ContentView
du `ʻUIScrollView`` est modifié (simplement, lorsque les coordonnées des éléments dans le ScrollView sont modifiées, la position d'affichage est modifiée par l'utilisateur. Il y a des moments où vous souhaitez unifier et afficher au centre du parchemin au lieu de le laisser décider, et l'utiliser dans de tels cas.)
La méthode appelée ici est layoutSubViews () ''. Cette méthode utilise les informations de contrainte pour créer les informations de trame. Vous pouvez appeler
layoutSubViews () '' à tout moment, tout comme la mise à jour des contraintes. L'appel de layoutIfNeeded ()
est marqué comme "les informations sur le cadre doivent être mises à jour" (peut être marqué en appelant setNeedsLayoutSubViews ()
) des vues auto et enfant Vous pouvez exécuter layoutSubViews ()
. De plus, les vues marquées avec `` setNeedsLayoutSubViews () '' seront mises à jour immédiatement au moment de la prochaine mise à jour de l'image (la synchronisation est laissée au système, mais celle-ci est recommandée * la raison sera décrite plus tard) C'est similaire à la mise à jour de, donc je ne vais pas l'expliquer en détail.
J'ai mentionné précédemment que layoutSubViews () qui a été exécuté au moment du système est meilleur, mais je vais expliquer pourquoi.
Il en va de même pour updateConstraints () pour la mise à jour des contraintes.
Veuillez noter que le traitement de layoutSubViews () '' appelé par
layoutSubViewsIfNeeded () '' est exécuté dans le thread principal. Cela peut ne pas être familier aux débutants, mais comprenez que le fil principal est comme la zone où le traitement a lieu. Et dans ce fil principal, des modifications de l'interface utilisateur sont également apportées ici. Par conséquent, si vous utilisez le thread principal avec layoutSubViewsIfNeeded () '', la mise à jour de l'interface utilisateur s'arrêtera pendant ce temps, ce qui peut affecter l'expérience utilisateur. Dans le cas d'un traitement qui semble être lié à l'interface utilisateur, appelons directement
layoutSubViews () ''. `` LayoutSubVIews () '' appelé à un rythme régulier peut être exécuté sans occuper le thread principal, donc cela n'affecte pas les modifications de l'interface utilisateur.
Il y a deux points à noter lors du remplacement. Le premier point est que vous devez d'abord exécuter super.layoutSubViews () ''. Le traitement de la mise à jour du cadre est effectué par
super.layoutSubViews () ''. Si vous ne le faites pas en premier, vous devrez écrire votre propre traitement sans mettre à jour le cadre, qui peut être un foyer de bogues. Le deuxième point est que les informations sur le cadre sont mises à jour à partir de la vue parente de manière descendante. Étant donné que la mise à jour est descendante, je peux modifier la disposition de la vue enfant, mais si je modifie la vue parente, `` layoutSubViews () '' sera appelé à nouveau et il plantera.
Ici, la vue est en fait dessinée à l'écran en utilisant les informations de cadre mises à jour. Ce processus est appelé au moment suivant.
-Déplacez ou supprimez la vue cachée ・ Lorsque la vue masquée est affichée -Faites défiler la vue vers l'extérieur de l'écran et revenez à l'écran.
La méthode appelée ici est drawRext (_ :) ''. Si vous souhaitez l'appeler à tout moment, vous pouvez l'appeler explicitement en le marquant avec
setNeededDisplay () '' ou `` setNeedsDisplayInRect () ''.
C'est tout pour cet article. Il est devenu plus volumineux que je ne l'imaginais, mais veuillez vous y référer. J'écrirai un article s'il y a de nouvelles découvertes.
Merci beaucoup.