39 votes

UIViewController renvoie une trame invalide?

Lorsque je lance ViewController en mode landscape (après l'appel de viewDidLoad), j'imprime le cadre, il me donne plutôt la taille du cadre pour le mode portrait.

Est-ce un bug des suggestions?

 - (void)viewDidLoad
{
   [super viewDidLoad];

   NSLog(@"%@", NSStringFromCGRect(self.view.frame));
   // Result is (0, 0 , 768, 1024)
}
 

158voto

rob mayoff Points 124153

Il ya un couple de choses que vous ne comprenez pas.

Tout d'abord, le système vous envoie viewDidLoad immédiatement après le chargement de votre plume. Il n'a pas encore ajouté de l'afficher à la vue de la hiérarchie encore. Donc, il n'est pas redimensionné votre vue en fonction de l'appareil de rotation soit.

Deuxièmement, une vue de l'image est dans son superview de coordonnées de l'espace. Si c'est votre vue de la racine, ses superview sera l' UIWindow (une fois que le système ajoute vraiment votre point de vue à la vue de la hiérarchie). L' UIWindow des poignées de rotation par la définition de la transformation de ses sous-vue. Cela signifie que le point de vue de l'image ne seront pas nécessairement ce que vous attendez.

Voici le point de vue de la hiérarchie en orientation portrait:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $1 = 0x09532dc0 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>>
   | <UIView: 0x9634ee0; frame = (0 20; 768 1004); autoresize = W+H; layer = <CALayer: 0x9633b50>>

et voici la vue de la hiérarchie dans le paysage de la gauche orientation:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $2 = 0x09635e70 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>>
   | <UIView: 0x9634ee0; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x9633b50>>

Remarquez que dans le paysage de l'orientation, de la taille de l'image est de 748 x 1024, pas de 1024 x 748.

Ce que vous voulez probablement à regarder, si c'est votre vue de la racine, est le point de vue de limites:

(lldb) p (CGRect)[0x9634ee0 bounds]
(CGRect) $3 = {
  (CGPoint) origin = {
    (CGFloat) x = 0
    (CGFloat) y = 0
  }
  (CGSize) size = {
    (CGFloat) width = 1024
    (CGFloat) height = 748
  }
}

Je suppose que vous voulez savoir quand le point de vue de la transformer, le cadre et les limites de mises à jour. Si l'interface est en mode paysage lorsque votre vue-contrôleur les charges de son point de vue, vous allez recevoir des messages dans cet ordre:

{{0, 0}, {768, 1004}} viewDidLoad
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} viewWillAppear:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} willRotateToInterfaceOrientation:duration:
{{0, 0}, {1024, 748}} viewWillLayoutSubviews
{{0, 0}, {1024, 748}} layoutSubviews
{{0, 0}, {1024, 748}} viewDidLayoutSubviews
{{0, 0}, {1024, 748}} willAnimateRotationToInterfaceOrientation:duration:
{{0, 0}, {1024, 748}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {1024, 748}} viewDidAppear:

Vous pouvez voir que votre vue les limites de changement après vous recevez willRotateToInterfaceOrientation:duration: et avant de vous recevoir viewWillLayoutSubviews.

L' viewWillLayoutSubviews et viewDidLayoutSubviews méthodes sont nouvelles pour iOS 5.0.

L' layoutSubviews message est envoyé à la vue, et non pas le point de vue du contrôleur, de sorte que vous aurez besoin de créer un personnalisé, UIView sous-classe si vous souhaitez l'utiliser.

3voto

Timo Points 560

Voici une solution propre.

Je vivais la même question, et j'insiste sur l'utilisation de l' frame tout au long de mon application. Je ne veux pas faire une exception pour la vue racine contrôleur. J'ai remarqué que la vue de la racine du contrôleur frame a l'affichage de portrait dimensions, mais tous les sous-vues a corriger paysage dimensions.

Puisque c'est seulement la vue racine contrôleur qui se comporte différemment, nous pouvons définir une norme, vide, vue sur le contrôleur de la vue de la racine de contrôleur et de l'ajouter à notre vue personnalisée contrôleur pour que. (Code ci-dessous.)

Vous pouvez ensuite utiliser frame que vous voulez, dans votre personnalisé-vue-contrôleur.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    self.window.rootViewController = [[UIViewController alloc] init];

    [self.window makeKeyAndVisible];

    self.viewController = [[ViewController alloc] initWithNibName:nil bundle:nil];
    [self.window.rootViewController addChildViewController:self.viewController];
    [self.window.rootViewController.view addSubview:self.viewController.view];

    return YES;
}

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