2017-09-15 2 views
1

, je trouve toujours mon auto aux prises avec la bonne solution.force mise en page automatique de mise à jour Aussi simple que cela pourrait être cadre UIView correctement à viewDidLoad

J'essaie de comprendre ce qui est le bon façon de trouver le cadre REALUIView (ou tout autre sous-vue) à l'intérieur viewDidLoad lors de l'utilisation Mise en page automatique.

Le problème principal est que, dans viewDidLoad, les vues ne sont pas appliquées à leurs contraintes. Je sais que le « connu » réponse à cette situation est

override func viewDidLoad() { 
     super.viewDidLoad() 
    view.layoutIfNeeded() 
    stepContainer.layoutIfNeeded() // We need this Subview real frame! 
    let realFrame = stepContainer.frame 
} 

Mais je trouve que cela ne fonctionne pas toujours, et de temps en temps, il cadre mal de donner (et non la dernière image qui est affichée).

Après quelques plus pour la recherche que je trouve que le gauchissement ce code sous DispatchQueue.main.async { } donne des résultats précis. Mais je ne suis pas sûr que ce soit la bonne façon de gérer cela, ou est-ce que je suis en train de créer des problèmes sous-jacents. Code final "travail":

override func viewDidLoad() { 
     super.viewDidLoad() 

     DispatchQueue.main.async { 
      self. stepContainer.layoutIfNeeded() 
      print(self. stepContainer.frame) // Real frame.. 
     } 

} 

NOTE: Je dois trouver ce qui est le cadre réel que de viewDidLoad, s'il vous plaît ne suggère pas utiliser viewDidAppear/layoutSubviews etc.

+3

viewDidLoad n'est pas l'endroit idéal pour mettre en place des choses qui exigent des connaissances des cadres, c'est la raison pour laquelle vous rencontrez ce problème – trapper

+0

@trapper Je suis au courant de cela. En raison d'un scénario spécifique que je dois résoudre ce (et il est résoluble) .. Je fais juste que je l'ai résolu la bonne façon –

+0

Qu'est-ce que vous ARME essaie de faire avec le cadre tôt dans le cycle de vie de la vue? –

Répondre

2

Comme @ DavidRönnqvist a souligné

ASYNC d'expédition raison vous donne la valeur « correcte » est ici que il ordonnancé à courir dans la prochaine boucle de course; après viewWillAppear et viewDidLayoutSubviews a exécuté.

Exemple

override func viewDidLoad() { 
    super.viewDidLoad() 
    DispatchQueue.main.async { 
    print("DispatchQueue.main.async viewDidLoad") 
    } 
} 

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 

    print("viewWillAppear") 
} 

override func viewDidAppear(_ animated: Bool) { 
    super.viewDidAppear(animated) 

    print("viewDidAppear") 
} 

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    print("viewDidLayoutSubviews") 
} 

viewWillAppear

viewDidLayoutSubviews

viewDidAppear

DispatchQueue.main.async viewDidLoad

Le code à l'intérieur DispatchQueue.main.async de viewDidLoad est même appelé après viewDidAppear. Donc, en utilisant DispatchQueue.main.async en viewDidLoad vous donne le cadre droit mais ce n'est pas le plus tôt possible.

Réponse

  • Si vous souhaitez obtenir bon état le plus tôt possible, viewDidLayoutSubviews est le bon endroit pour le faire. Si vous devez mettre du code à l'intérieur viewDidLoad, vous le faites correctement. Semblez comme DispatchQueue.main.async est le meilleur moyen de le faire.

1

Après avoir lu les commentaires , vous pouvez peut-être essayer d'intégrer votre contrôleur de vue dans un autre avec un récipient et faire quelque chose comme ceci:

  • Dans le contrôleur de vue parent ajouter une variable: var viewSize : CGSize?
  • Dans le contrôleur de vue enfant ajouter une variable: var parentViewSize : CGSize?
  • Dans le contrôleur de vue parent, obtenir la taille dans le viewDidLayoutSubViews et le stocker: viewSize = view.size
  • Dans le contrôleur de vue parent, dans la prepareForSegue envoyer la taille que vous avez enregistré: (destinationViewController as? MyViewController)?.parentViewSize = viewSize
  • dans le contrôleur de vue de l'enfant, dans le viewDidLoad vous aurez accès à la variable parentViewSize avec la bonne valeur en elle

ne serait-il le faire?

1

Votre question est similaire à this problem, et ma réponse sera également la même.

Il n'est pas garanti que le cadre soit identique dans viewDidLoad comme il le sera lors de l'affichage de la vue. UIKit ajuste le cadre de la vue de votre contrôleur de vue avant de le présenter, en fonction du contexte dans lequel apparaîtra. Pour une meilleure compréhension du cycle de vie des vues, vous pouvez vous référer à cette image. enter image description here

L'image vous aidera à comprendre pourquoi votre code fonctionne. Comme l'image montre que viewWillAppear est appelée une fois qu'une vue est chargée et lorsque vous configurez dispatch async, elle est ajoutée au thread de façon asynchrone après l'exécution de viewWillAppear. Ainsi, une fois que viewWillAppear est appelée, vos cadres sont mis à jour en fonction de votre vue, et vous obtenez l'image correcte lors de l'envoi asynchrone.

Références: Image source

For more information about view life cycle you can visit this answer

Alors, enfin, vous pouvez aller pour l'une des deux options:

  1. Si vous souhaitez utiliser la mise en page automatique gérer certaines images soit dans viewDidLayoutSubviews ou viewWillAppear. (Dans l'un ou l'autre de ces viewDidLayoutSubview, on devrait aller car viewWillAppear sera appelé chaque fois que votre vue apparaîtra en haut de la hiérarchie de la vue, cela ne devrait pas être préféré).
  2. Si vous souhaitez ignorer la mise en forme automatique, vous pouvez créer et gérer des vues par programmation.

Espérons que cela aide!

+0

Vous devriez jeter un oeil à cette question https://stackoverflow.com/questions/14060002/wrong-frame-size-in-viewdidload. Je pense que 'viewWillAppear' n'est pas le bon choix pour (1). – trungduc

+0

D'accord, c'est pourquoi j'ai mentionné soit. Je vais l'éditer pour être plus précis. Merci de l'avoir signalé. –

+0

On dirait avoir mal compris ici;). Je veux dire * Lorsque vous utilisez autolayout dans ios6, les images ne sont pas définies tant que les sous-vues n'ont pas été mises en page. Le bon endroit pour obtenir des données d'image dans ces conditions est dans la méthode viewController 'viewDidLayoutSubviews' *. C'est ** update (ios6) ** dans la réponse. – trungduc