UIViewController rotate methods

¿Qué object es responsable de distribuir las llamadas del método de rotation UIViewController , es decir:

  • shouldAutorotateToInterfaceOrientation:
  • willRotateToInterfaceOrientation:duration:
  • willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
  • willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:

Me imagino que es UIApplication (pero tal vez AppDelegate o UIWindow).

La siguiente pregunta es ¿cómo sabe el object con qué UIViewController hablar?

¿Cómo sabe que UIViewController tiene su vista como subview de la window?

¿Hay un post que puede enviar o una propiedad que puede configurar (de algún object) que establece el UIViewController "Activo" para la aplicación?

Parece que UIApplication está enviando un post al controller de vista activo.

Pero, ¿cómo obtiene su instancia View Controller estos posts?

El post se reenvía al primer controller de vista cuya vista se ha agregado a la instancia de UIWindow .

Esto se networkinguce a 3 escenarios básicos:

  1. El ViewController cuya vista se agrega directamente a la instancia de UIWindow (aplicación de vista única)

  2. El controller de navigation en una aplicación basada en navigation, luego el controller de navigation reenvía el post al controller de vista de vistas activas.

  3. El controller de barra de tabs en una aplicación basada en barra de tabs, luego el controller de barra de tabs envía el post al controller de vista de vistas activas (o al controller de navigation activo).

El problema que tendrá será si crea una aplicación con varias vistas, pero NO use un controller de navigation o un controller de barra de tabs. Si intercambia vistas dentro y fuera de la instancia de UIWindow manualmente, no recibirá estos posts de manera confiable. Esto es similar a publicaciones como esta: la vista de iPhone no funcionará y no se dispara

Solo usa las convenciones de Apple para múltiples vistas y estarás bien. Espero que esto salve a alguien una hora o dos

¿Cómo sabe que UIViewController tiene su vista como subview de la window?

La class UIViewController mantiene un map estático entre las vistas y sus controlleres de vista. Este map se consulta en algunos lugares key dentro de CocoaTouch. En particular, [UIVview nextResponder] lo consulta y devuelve el controller si se encuentra.

Supongo que UIWindow realiza la misma búsqueda con su vista raíz para saber a qué controller enviar events de rotation. Verificará esto la próxima vez que busque algo en el desassembly. (He invertido un time en la ingeniería inversa CocoaTouch para comprender cómo funcionan las cosas allí).

Esta es toda la magia que nunca te preocupes. Simplemente agregue la vista raíz de su controller a la window, o obtenga una barra de tabs o controller de navigation para hacerlo por usted, y recibirá estos posts.

(Pero si examina el depurador, puede llegar a la misma conclusión que tengo: hay una especie de tabla interna que mapea la vista de cada controller al controller, y los posts se envían según ese enlace).


Actualización: esta fue una auténtica magia privada en 2009 cuando escribí esta respuesta por primera vez, pero los cambios subsiguientes a iOS han hecho públicas las API detrás de ella. El controller de vista raíz ahora se puede acceder a través de la propiedad UIWindow.rootViewController y el tree de los controlleres de vista descendente se forma utilizando la propiedad UIViewController.childViewControllers .

Los controlleres de vista principal son responsables de notificar a sus hijos sobre los cambios de orientación. (No estoy seguro de cómo se notifica al controller de vista raíz, pero puede establecer un punto de interrupción y descubrirlo usted mismo). El método -shouldAutomaticallyForwardRotationMethods decide si UIViewController hará esto por usted. Si devuelve NO , -willRotateToInterfaceOrientation:duration: responsable de hacerlo en su -willRotateToInterfaceOrientation:duration: -willAnimateRotationToInterfaceOrientation:duration: y -didRotateFromInterfaceOrientation: methods.

Tengo un problema similar.

Tengo un juego que trabaja en orientación horizontal (paisaje izquierdo y derecho).

Para administrar una aplicación multivista, utilizo un UIviewController raíz, es decir, un UMIiewcontroller ficticio con una UIview que no hace nada. A continuación, agrego cada otra UIview como una subvista.

Al iniciar la aplicación, el emulador gira rápidamente a una orientación vertical y obtengo cada una de mis vistas con su propiedad de marco (0, -80,320,480). Esto hace que la vista sea recortada por un rectángulo de 160 x 320 en el lado derecho.

Me he dado count de que el método shouldAutorotateToInterfaceOrientation: de cada subvista solo se llama una vez, y eso sucede cuando se agrega a la vista raíz. Más tarde, al girar el dispositivo, solo la vista raíz recibe su método llamado.

Como era de esperar, cualquiera de las llamadas a los methods willAnimate * solo se enviará a la vista raíz, por lo que definir cualquiera de estos methods en las subvenciones no tiene sentido.

Estos methods se llaman cada vez que la orientación se cambia a una orientación aceptada por el método shouldAutorotateToInterfaceOrientation:. así que pensé que podría cambiar la propiedad de marco de mi subvención desde allí.

Para lograr esto, definí el siguiente método en mi class rootViewController:

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { subview1_ViewController.view.frame = CGRectMake(0,0,480,320); subview2_ViewController.view.frame = CGRectMake(0,0,480,320); ... } 

No entiendo por qué la propiedad de marco no se actualiza, pero sé que esta solución funciona.

Espero que esto ayude….