web-dev-qa-db-fra.com

iOS AutoLayout - Obtenir la taille du cadre

Je développe en utilisant iOS 6 auto layout

Je souhaite consigner un message indiquant la largeur du cadre de la vue.

Je peux voir le texte sur l'écran.

Mais la largeur et la hauteur sont égales à zéro, quelque chose me manque-t-il?

NSLog(@"textView    = %p", self.textView);
NSLog(@"height      = %f", self.textView.frame.size.height);
NSLog(@"width       = %f", self.textView.frame.size.width);

textView    = 0x882de00
height      = 0.000000
width       = 0.000000
57
user1046037

Je pense que la mise en page automatique n'a pas eu le temps de mettre en page vos vues au moment où vous appelez cela. La mise en page automatique n'a pas encore eu lieu au moment où viewDidLoad est appelé, car il est appelé juste après le chargement des vues et c'est seulement après que les vues sont placées dans la hiérarchie de vues du contrôleur de vue et finalement présentées (dans la méthode layoutSubviews de la vue).

Modifier: cette réponse indique pourquoi le scénario de la question ne fonctionne pas. La réponse de @ dreamzor indique l'emplacement de votre code pour le résoudre.

56
Jesper

En fait, les réponses ci-dessus ne sont pas tout à fait correctes. Je les ai suivis et ai obtenu des zéros encore et encore. 

L'astuce consiste à placer votre code dépendant du cadre dans la méthode viewDidLayoutSubviews, qui 

Notifie le contrôleur de vue que sa vue vient de définir ses sous-vues.

N'oubliez pas que cette méthode s'appelle plusieurs fois et ne fait pas partie du cycle de vie de ViewController. Soyez donc prudent lorsque vous l'utilisez. 

J'espère que cela sera utile à quelqu'un.

Je voulais juste ajouter que, pour mon programme sans mode paysage, NE PAS utiliser la mise en page automatique est beaucoup plus simple ... J'ai essayé, cependant = D 

151
dreamzor

Solution

  • Placez ce code dans viewDidAppear

Raison

  • viewDidLoad survient avant que l'autolayout ne soit terminé. Donc, la position n'est pas encore définie par autolayout qui a été spécifié dans xib
  • viewDidAppear survient après la fin de l'autolayout.
29
user1046037

Inclure dans votre viewDidLoad ()

self.view.setNeedsLayout()
self.view.layoutIfNeeded()

Avant d'accéder à yourview.frame.size.width

28
diegosantiviago

En fait, j'ai réussi à forcer la mise à jour de la mise en page avant mon code dans la variable viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()

        println("bounds before \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds before (0.0,0.0,320.0,320.0)

        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()

        println("bounds after \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds after (0.0,0.0,414.0,414.0)

        //Size dependent code works here
        self.create()
    }

UPDATE: Cela ne semble plus fonctionner

13
Francescu

C'est une fonctionnalité vraiment étrange. Mais j'ai trouvé:

Si vous voulez obtenir un cadre sans utiliser la méthode layoutsubviews, utilisez celui-ci:

dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"View frame: %@", NSStringFromCGRect(view.frame));
    });

C'est vraiment étrange !!!

9
SamSol

Aucune des réponses ci-dessus n'a fonctionné complètement pour moi, à l'exception de viewDidLoad, mais cela a pour effet secondaire de ne pas afficher ce que je veux tant que la vue n'est pas animée, ce qui semble médiocre.

viewDidLayoutSubviews devrait être le bon endroit pour exécuter du code reposant sur la fin de la mise en mémoire automatique, mais comme l'ont souligné d'autres personnes, il est appelé plusieurs fois dans les versions récentes de iOS et vous ne pouvez pas savoir quel est le dernier appel.

J'ai donc résolu cela avec un petit bidouillage. Dans mon storyboard, mySubview devrait être plus petit que son self.view contenant. Mais lorsque viewDidLayoutSubviews est appelé pour la première fois, mySubview a toujours une largeur de 600, alors que self.view semble être défini correctement (il s'agit d'un projet iPhone). Donc, tout ce que je dois faire est de surveiller les appels suivants et de vérifier les largeurs relatives. Une fois que mySubview est plus petit que self.view, je peux être sûr que tout a été disposé correctement. 

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if self.mySubview.bounds.size.width < self.view.bounds.size.width {

        // mySubview's width became less than the view's width, so it is
        // safe to assume it is now laid out correctly...

    }
}

Cela présente l'avantage de ne pas dépendre de chiffres codés en dur, ce qui permet de fonctionner avec tous les facteurs de forme de l'iPhone, par exemple. Bien sûr, cela peut ne pas être une panacée dans tous les cas ni sur tous les appareils, mais il existe probablement de nombreux moyens ingénieux de procéder à des contrôles similaires de tailles relatives. 

Et non, nous ne devrions pas avoir à faire cela, mais jusqu'à ce qu'Apple nous donne des rappels plus fiables, nous sommes tous coincés avec.

7
Echelon

iOS AutoLayout - Obtenir la taille du cadre

 -(void) layoutSubviews{
        [self layoutIfNeeded];
        //right you code to set frame its will work to get frame and set frame.
        CALayer *bottomBorder = [CALayer layer];
        bottomBorder.frame = CGRectMake(0.0f, bkView.frame.size.height - 1, bkView.frame.size.width, 1.0f);
        bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
        [bkView.layer addSublayer:bottomBorder];
    }
2
Ravi H Malviya

Vous ne pouvez connaître la taille qu'après la première passe de mise en page. Ou appelez simplement la méthode ci-dessous, après avoir obtenu la largeur réelle de votre vue.

[yourView layoutIfNeeded];
0
Bhavesh Patel