tutorial life example containerviewcontroller container iphone ios cocoa-touch uiviewcontroller

iphone - example - lifecycle viewcontroller ios



UIViewController rotar métodos (4)

¿Cómo sabe qué UIViewController tiene su vista como subvista de la ventana?

La clase UIViewController mantiene un mapa estático entre las vistas y sus controladores de vista. Este mapa se consulta en algunos lugares clave dentro de CocoaTouch. En particular, [UIView nextResponder] lo consulta y devuelve el controlador si se encuentra.

Supongo que UIWindow hace la misma búsqueda con su vista raíz para saber a qué controlador reenviar los eventos de rotación. Comprobaré esto la próxima vez que buscaré algo en el desmontaje. (He invertido un tiempo en la ingeniería inversa CocoaTouch para entender cómo funcionan las cosas allí).

¿Qué objeto es responsable de dipatear las llamadas al método de rotación UIViewController , es decir:

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

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

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

¿Cómo sabe qué UIViewController tiene su vista como subvista de la ventana?

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


Tengo un problema similar.

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

Para administrar una aplicación de vistas múltiples, utilizo un UIviewController raíz, es decir, un controlador UIView ficticio con una UIview que no hace nada. Luego agrego todos los demás 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 con el aspecto (0, -80,320,480). Esto hace que la vista quede recortada por un rectángulo de 160 X 320 en el lado derecho.

Me di cuenta de que el método "shouldAutorotateToInterfaceOrientation:" de cada subvista solo se llama una vez, y eso ocurre cuando se agrega a la vista raíz. Más adelante, al girar el dispositivo, solo la vista de raíz obtiene su método llamado.

Como era de esperar, cualquiera de las llamadas a los métodos "willAnimate *" solo se envían a la vista raíz, por lo tanto, la definición de cualquiera de estos métodos en las subvistas no tiene sentido.

Estos métodos se invocan cada vez que se cambia la orientación a una orientación aceptada por el método - shouldAutorotateToInterfaceOrientation :. así que pensé que podría modificar la propiedad de marco de mis subvistas desde allí.

Para lograr esto, definí el siguiente método en mi clase 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 frame no está actualizada, pero sé que esta solución alternativa funciona.

Espero que esto ayude....


Esto es todo magia de la que nunca te preocupes. Simplemente agregue la vista raíz de su controlador a la ventana, o obtenga una barra de pestañas o un controlador de navegación para que lo haga por usted, y recibirá estos mensajes.

(Pero si hurgas con el depurador, puedes llegar a la misma conclusión que tengo: hay algún tipo de tabla interna que asigna la vista de cada controlador al controlador, y los mensajes se envían según ese enlace).

Actualización: esta fue una magia realmente privada en 2009 cuando escribí esta respuesta por primera vez, pero los cambios posteriores a iOS han hecho que las API detrás de esto sean públicas. Ahora se puede acceder al controlador de vista raíz a través de la propiedad UIWindow.rootViewController , y el árbol de los controladores de vista descendientes se forma utilizando la propiedad UIViewController.childViewControllers .

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


Parece que UIApplication está enviando un mensaje al controlador de vista activo.

¿Pero cómo obtiene su instancia de View Controller estos mensajes?

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

Esto se reduce a 3 escenarios básicos:

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

  2. El controlador de navegación en una aplicación basada en navegación, luego el controlador de navegación reenvía el mensaje al controlador de vista de vistas activo.

  3. La barra de pestañas Controlador en una aplicación basada en barra de pestañas, luego el controlador de la barra de pestañas reenvía el mensaje al controlador de vista de vistas activo (o al controlador de navegación activo).

El problema que tendrá es si construye una aplicación con varias vistas, pero NO use un controlador de navegación o un controlador de barra de pestañas. Si intercambia puntos de vista dentro y fuera de la instancia de UIWindow manualmente, no recibirá estos mensajes de manera confiable. Esto es similar a publicaciones como esta: iPhone viewWillAppear no dispara

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