tutorial life example containerviewcontroller container ios xcode uiviewcontroller rotation bounds

example - lifecycle viewcontroller ios



Obteniendo los lĂ­mites correctos de la vista de UIViewController (5)

Esto es lo que encontré en mi último proyecto: el marco de self.view se ajustará después de viewDidLoad de acuerdo con si esta pantalla tiene barra de navegación, etc.

Así que tal vez quiera usar ese valor después de viewDidLoad (quizás en viewWillAppear o viewDidAppear) o ajustarlo manualmente restando la altura de las barras.

Tengo una aplicación para iPad. En orientación horizontal, la UIViewController del UIViewController es el ancho real = 1024px y la altura = 768 - 20 (barra de estado) - 44 ( 704px navegación) = 704px .

Así que quiero obtener este tamaño [1024 x 704] y estoy usando self.view.bounds para ello. Devuelve [748 x 1024] , ¡lo cual es incorrecto! Pero cuando giro la pantalla dos veces (actual -> retrato -> actual), los límites de la vista son correctos - [1024 x 704] .

La vista se inicializó así:

- (void)loadView { self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; self.view.backgroundColor = [UIColor lightGrayColor]; }

Y los límites fueron así:

- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds)); } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { NSLog(@"bounds = %@", NSStringFromCGRect(self.view.bounds)); }

Entonces la pregunta es ... ¿Cómo puedo obtener la vista correcta desde el principio?


Siempre he usado:

CGSize sizeOfScreen = [[UIScreen mainScreen] bounds].size;

para obtener el tamaño de la pantalla, y:

CGSize sizeOfView = self.view.bounds.size;

para obtener el tamaño de la view . Acabo de probarlo en viewDidLoad y me devolvió:

2012-07-17 10:25:46.562 Project[3904:15203] bounds = {768, 1004}

Lo cual es correcto ya que CGSize se define como {ancho, alto}.


Me encontré con este problema y descubrí que obtener los límites en viewDidAppear funcionaba para mis necesidades.


Según algunas de las otras respuestas, el problema que está viendo es porque se llama a viewDidLoad antes de que ocurra la rotación. Debido a que el iPad siempre se inicializa en modo retrato, si obtiene los valores de tamaño en viewDidLoad , siempre serán los tamaños de retrato, independientemente de las orientaciones que haya configurado.

Para obtener el tamaño después de la orientación / rotación, obtenga los valores de tamaño en viewDidAppear .

No entiendo particularmente por qué iOS no lo maneja mejor, especialmente dado que define las orientaciones en la configuración del proyecto y, en Xcode Interface Builder. Pero, estoy seguro de que hay una buena razón ;-).


Cómo hacer esto correctamente

Su subclase UIViewController debe anular el método viewWillLayoutSubviews , consulte también aquí .

Cuando se llama a este método, la view del viewController tiene su tamaño correcto y puede realizar los ajustes necesarios en las subvistas antes de que el diseño pase sobre las subvistas.

Documentación.

Cuando cambian los límites de una vista , la vista ajusta la posición de sus subvistas. El controlador de vista puede anular este método para realizar cambios antes de que la vista muestre sus subvistas. La implementación predeterminada de este método no hace nada.

Como puede ver en la parte destacada, se llama a este método cada vez que la vista del controlador de vista cambia de tamaño, así como también cuando aparece la vista por primera vez. Esto le permite responder correctamente a la rotación y otros eventos de cambio de límites

Algunas formas equivocadas de hacer esto.

Un par de métodos sugeridos por otras respuestas aquí no funcionan bien están completamente rotos. Realmente no deberías usar estos métodos. Aquí están, con por qué deberías evitarlos. Por favor.

  • viewDidLoad y viewWillAppear : durante estas llamadas, la view todavía no tiene su tamaño final. El tamaño que obtengas solo será correcto por pura casualidad , a fin de engañarte. Por favor, te lo ruego, no uses estos métodos.
  • viewDidAppear : esto es demasiado tarde. Su vista ya está en la pantalla y es visible para el usuario . Hacer cambios aquí provocará cambios visibles / fallas técnicas abruptas y se verá como una terrible basura de hora amateur. Una vez más, por favor, por su bien, por mi bien, por el bien de todos : ¡no lo hagas! Eres mejor que eso y también lo son tus usuarios.

Además de no proporcionar la información correcta, estos enfoques rotos no lo ayudarán con la rotación automática u otros eventos que causen que la vista del controlador de vista cambie de tamaño, como los gestos de multitarea. Esto es algo que realmente quieres manejar sin problemas.

Entonces, por favor: sé un campeón. Hazlo de la manera correcta. Use viewWillLayoutSubviews . Se solicitará su implementación para cada cambio de tamaño, y sus usuarios, futuro yo, miembros del equipo y yo lo celebraremos por ello. ¡Bravo!

Otros consejos.

Cuando se llama a viewWillLayoutSubviews , la única vista en su jerarquía que se redimensionará a su tamaño final es viewController.view . El regalo para esto está en el nombre del método. Te está diciendo que …WillLayout… view… (la vista de tu controlador de view ) …WillLayout… (muy pronto ahora, pero aún no ha sucedido) …Subviews (todo lo demás en su jerarquía bajo la vista raíz).

Pero aún no ha sucedido. Por lo tanto, todos los niños menores de la raíz aún no tienen un tamaño final válido. Cualquier información de tamaño que consulte desde las vistas secundarias será, en el mejor de los casos, completamente incorrecta.

¡Algo más probable, e infinitamente peor , será engañosamente correcto !

Resulta ser lo que espera y necesita debido a un valor predeterminado en este tamaño y orientación, o debido a la configuración del guión gráfico. Pero esto es solo por casualidad y no es algo en lo que pueda confiar con diferentes tamaños de dispositivos u orientaciones.

Si necesita que le digan cuándo una subvista particular cambia de tamaño y conoce su tamaño final exacto, debe anular el método layoutSubviews de esa subclase particular de UIView .