ios - UIViewController devuelve un marco no válido
landscape (2)
Aquí hay una solución limpia.
Estaba experimentando el mismo problema e insisto en usar frame
en mi aplicación. No quiero hacer una excepción para el controlador de vista raíz. Noté que el frame
del controlador de vista raíz mostraba las dimensiones de retrato, pero todas las subvistas tenían las dimensiones de paisaje correctas .
Como solo el controlador de vista raíz se comporta de manera diferente, podemos establecer un controlador de vista estándar en blanco como controlador de vista raíz y agregar nuestro controlador de vista personalizado a eso. (Código a continuación)
Luego puede usar el frame
como lo desea, en su controlador de vista personalizado.
- (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;
}
Cuando inicio mi ViewController en modo landscape
(después de llamar a viewDidLoad), imprimo el cuadro que me da el tamaño de fotograma para el modo vertical.
¿Es esto un error alguna sugerencia?
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%@", NSStringFromCGRect(self.view.frame));
// Result is (0, 0 , 768, 1024)
}
Hay un par de cosas que no entiendes.
Primero, el sistema le envía viewDidLoad
inmediatamente después de cargar su plumilla. Ni siquiera ha agregado la vista a la jerarquía de vistas todavía. Por lo tanto, no ha cambiado el tamaño de su vista en función de la rotación del dispositivo.
En segundo lugar, el marco de una vista se encuentra en el espacio de coordenadas de su supervista. Si esta es su vista raíz, su supervista será la UIWindow
(una vez que el sistema realmente agregue su vista a la jerarquía de vista). La UIWindow
maneja la rotación configurando la transformación de su subvista. Esto significa que el marco de la vista no será necesariamente lo que esperas.
Aquí está la jerarquía de vista en orientación vertical:
(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>>
y aquí está la jerarquía de vista en orientación horizontal izquierda:
(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>>
Observe que en orientación horizontal, el tamaño del marco es 748 x 1024, no 1024 x 748.
Lo que probablemente quiera ver, si esta es su vista raíz, son los límites de la vista:
(lldb) p (CGRect)[0x9634ee0 bounds]
(CGRect) $3 = {
(CGPoint) origin = {
(CGFloat) x = 0
(CGFloat) y = 0
}
(CGSize) size = {
(CGFloat) width = 1024
(CGFloat) height = 748
}
}
Presumiblemente, desea saber cuándo se actualizan la transformación, el marco y los límites de la vista. Si la interfaz tiene una orientación horizontal cuando el controlador de vista carga su vista, recibirá los mensajes en este orden:
{{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:
Puede ver que los límites de su vista cambian después de recibir willRotateToInterfaceOrientation:duration:
y antes de recibir viewWillLayoutSubviews
.
Los métodos viewWillLayoutSubviews
y viewDidLayoutSubviews
son nuevos en iOS 5.0.
El mensaje layoutSubviews
se envía a la vista, no al controlador de vista, por lo que deberá crear una subclase UIView
personalizada si desea usarla.