La vista de iPhone no aparecerá disparando

He leído numerosas publicaciones sobre personas que tienen problemas con viewWillAppear cuando no creas la jerarquía de vistas correcta. Mi problema es que no puedo entender lo que eso significa.

Si creo un RootViewController y llamo addSubView en ese controlador, esperaría que las vistas agregadas se conectaran para los eventos viewWillAppear .

¿Alguien tiene un ejemplo de jerarquía compleja de vistas programáticas que recibe con viewWillAppear eventos viewWillAppear en todos los niveles?

Estado de los documentos de Apple:

Advertencia: si la vista que pertenece a un controlador de vista se agrega a una jerarquía de vista directamente, el controlador de vista no recibirá este mensaje. Si inserta o agrega una vista a la jerarquía de vista, y tiene un controlador de vista, debe enviar este controlador directamente al mensaje de vista asociado. Si no se envía el controlador de vista, este mensaje evitará que se muestre ninguna animación asociada.

El problema es que no describen cómo hacer esto. ¿Qué significa “directamente”? ¿Cómo agregas “indirectamente” una vista?

Soy bastante nuevo en Cocoa y iPhone, por lo que sería bueno que hubiera ejemplos útiles de Apple además de la basura básica de Hello World.

Si usa un controlador de navegación y establece su delegado, los métodos view {Will, Did} {Appear, Disappear} no se invocan.

En su lugar, debe usar los métodos de delegado del controlador de navegación:

 navigationController:willShowViewController:animated: navigationController:didShowViewController:animated: 

Me he encontrado con este mismo problema. Simplemente envíe un mensaje viewWillAppear a su controlador de vista antes de agregarlo como una subvista. (Hay un parámetro BOOL que le dice al controlador de vista si está siendo animado para aparecer o no).

 [myViewController viewWillAppear:NO]; 

Mire RootViewController.m en el ejemplo de Metronome.

(De hecho, encontré excelentes proyectos de ejemplo de Apple. Hay MUCHO más que HelloWorld;)

¡Finalmente encontré una solución para esto QUE FUNCIONA!

UINavigationControllerDelegate

Creo que lo esencial es configurar el delegado de control de navegación en el controlador de vista en el que se encuentra, e implementar UINavigationControllerDelegate y sus dos métodos. ¡Brillante! Estoy tan emocionado que finalmente encontré una solución!

Solo tuve el mismo problema. En mi aplicación tengo 2 controles de navegación y presiono el mismo controlador de vista en cada uno de ellos trabajando en un caso y no en el otro. Me refiero a que al presionar exactamente el mismo controlador de vista en el primer UINavigationController , se llamaba viewWillAppear pero no cuando se viewWillAppear en el segundo controlador de navegación.

Luego me encontré con esta publicación UINavigationController debería llamar a los métodos viewWillAppear / viewWillDisappear

Y me di cuenta de que mi segundo controlador de navegación redefinió viewWillAppear . La detección del código mostró que no estaba llamando

 [super viewWillAppear:animated]; 

¡Lo agregué y funcionó!

La documentación dice:

Si anula este método, debe llamar a super en algún momento de su implementación.

He estado usando un controlador de navegación. Cuando deseo descender a otro nivel de datos o mostrar mi vista personalizada, uso lo siguiente:

 [self.navigationController pushViewController: animated:]; 

Cuando hago esto, obtengo la función viewWillAppear para disparar. Supongo que esto califica como “indirecto” porque no estoy llamando al método addSubView real. No sé si esto es 100% aplicable a su aplicación, ya que no puedo decir si está usando un controlador de navegación, pero tal vez le proporcione una pista.

En primer lugar, la barra de tabs debe estar en el nivel raíz, es decir, agregado a la ventana, como se indica en la documentación de Apple. Esto es clave para un comportamiento correcto.

En segundo lugar, puede usar UITabBarDelegate / UINavigationBarDelegate para reenviar las notificaciones manualmente, pero descubrí que para que todas las llamadas a la jerarquía de vista funcionen correctamente, todo lo que tenía que hacer era llamar manualmente

 [tabBarController viewWillAppear:NO]; [tabBarController viewDidAppear:NO]; 

y

 [navBarController viewWillAppear:NO]; [navBarController viewDidAppear:NO]; 

.. solo UNA VEZ antes de configurar los controladores de vista en el controlador respectivo (justo después de la asignación). Desde ese momento, llamó correctamente estos métodos en sus controladores de vista secundarios.

Mi jerarquía es así:

 window UITabBarController (subclass of) UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear UINavigationController (subclass of) UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods 

Simplemente llamando a los métodos mencionados en el controlador tab / nav la primera vez aseguró que TODOS los eventos se reenviaron correctamente. Me detuvo la necesidad de llamarlos manualmente desde los métodos UINavigationBarDelegate / UITabBarControllerDelegate .

Sidenote: Curiosamente, cuando no funcionó, el método privado

 - (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController 

... que se puede ver desde la stack de llamadas en una implementación en funcionamiento, normalmente llama a los viewWill/Did.. pero no hasta que realicé lo anterior (aunque se haya llamado).

Creo que es MUY importante que el UITabBarController esté al nivel de la ventana y los documentos parecen respaldar esto.

Espero que haya sido claro (ish), feliz de responder más preguntas.

Como no se acepta ninguna respuesta y la gente (como yo) aterrizó aquí doy mi variación. Aunque no estoy seguro de que ese fuera el problema original. Cuando el controlador de navegación se agrega como una vista secundaria a otra vista, debe llamar a los métodos viewWillAppear / Dissappear, etc., de la siguiente manera:

 - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [subNavCntlr viewWillAppear:animated]; } - (void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [subNavCntlr viewWillDisappear:animated]; } 

Solo para completar el ejemplo. Este código aparece en mi ViewController donde creé y agregué el controlador de navegación en una vista que coloqué en la vista.

 - (void)viewDidLoad { // This is the root View Controller rootTable *rootTableController = [[rootTable alloc] initWithStyle:UITableViewStyleGrouped]; subNavCntlr = [[UINavigationController alloc] initWithRootViewController:rootTableController]; [rootTableController release]; subNavCntlr.view.frame = subNavContainer.bounds; [subNavContainer addSubview:subNavCntlr.view]; [super viewDidLoad]; } 

el .h se ve así

 @interface navTestViewController : UIViewController  { IBOutlet UIView *subNavContainer; UINavigationController *subNavCntlr; } @end 

En el archivo nib tengo la vista y debajo de esta vista tengo una etiqueta de una imagen y el contenedor (otra vista) donde puse el controlador. Así es como se ve. Tuve que pelear algunas cosas ya que esto era trabajo para un cliente.

texto alternativo

Las vistas se agregan “directamente” al llamar a [view addSubview:subview] . Las vistas se agregan “indirectamente” mediante métodos como barras de tabs o barras de navegación que intercambian subvistas.

Siempre que llame a [view addSubview:subviewController.view] , debe llamar a [subviewController viewWillAppear:NO] (o YES, según sea el caso).

Tuve este problema cuando implementé mi propio sistema de administración de vistas de raíz para una pantalla secundaria en un juego. La adición manual de la llamada a viewWillAppear solucionó mi problema.

La forma correcta de hacerlo es usar la API de contención UIViewController.

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. UIViewController *viewController = ...; [self addChildViewController:viewController]; [self.view addSubview:viewController.view]; [viewController didMoveToParentViewController:self]; } 

Uso este código para controles de vista push y pop:

empujar:

 [self.navigationController pushViewController:detaiViewController animated:YES]; [detailNewsViewController viewWillAppear:YES]; 

popular:

 [[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES]; 

.. y funciona bien para mí.

Un error muy común es el siguiente. Usted tiene una vista, UIView* a , y otra, UIView* b . Agrega b a a como una subvista. Si intentas llamar a viewWillAppear en b, nunca se disparará, porque es una subvista de un

No estoy 100% seguro de esto, pero creo que agregar una vista a la jerarquía de vista directamente significa llamar -addSubview: en la vista del controlador de vista (por ejemplo, [viewController.view addSubview:anotherViewController.view] ) en lugar de presionar un nuevo controlador de vista en la stack del controlador de navegación.

Creo que agregar una subvista no necesariamente significa que la vista aparecerá, por lo que no hay una llamada automática al método de la clase que lo haga

Creo que lo que quieren decir “directamente” es conectar las cosas de la misma manera que lo hace la plantilla xcode “Aplicación de navegación”, que establece el UINavigationController como la única subvista de la ventana de UI de la aplicación.

Usar esa plantilla es la única forma en que pude obtener los métodos Will / Did / Appear / Disappear llamados en el objeto ViewControllers luego de los push / pops de esos controladores en el UINavigationController. Ninguna de las otras soluciones en las respuestas aquí funcionó para mí, incluso implementarlas en RootController y pasarlas al control de navegación (hijo). Esas funciones (will / did / appear / disappear) solo se llamaron en mi RootController al mostrar / ocultar los VCs de nivel superior, mi “login” y navigationVCs, no los sub-VCs en el controlador de navegación, por lo que no tuve la oportunidad de “páselos” al Nav VC.

Terminé usando la funcionalidad de delegado de UINavigationController para buscar las transiciones particulares que requerían la funcionalidad de seguimiento en mi aplicación, y eso funciona, pero requiere un poco más de trabajo para que desaparezca y aparezca la funcionalidad “simulada”.

También es una cuestión de principios hacer que funcione después de golpear mi cabeza contra este problema durante horas hoy. Cualquier fragmento de código que funcione utilizando un RootController personalizado y un VC de navegación infantil sería muy apreciado.

En caso de que esto ayude a alguien. Tuve un problema similar cuando mi ViewWillAppear no se ViewWillAppear en un UITableViewController . Después de jugar mucho, me di cuenta de que el problema era que el UINavigationController que está controlando mi UITableView no está en la vista raíz. Una vez que lo soluciono, ahora está funcionando como un campeón.

Simplemente tuve este problema yo mismo y tardé 3 horas completas (2 de las cuales en Google) para solucionarlo.

Lo que resultó útil fue simplemente eliminar la aplicación del dispositivo / simulador, limpiarla y luego ejecutarla nuevamente .

Espero que ayude

 [self.navigationController setDelegate:self]; 

Establezca el delegado en el controlador de vista raíz.

No estoy seguro de que este es el mismo problema que he resuelto.
En algunas ocasiones, el método no se ejecuta de manera normal, como “[self methodOne]”.

Tratar

 - (void)viewWillAppear:(BOOL)animated { [self performSelector:@selector(methodOne) withObject:nil afterDelay:0]; } 

Solo debe tener 1 UIViewController activo en cualquier momento. Cualquier subvista que quiera manipular debe ser exactamente eso – SUBVIEWS – es decir, UIView.

Utilizo una técnica sencilla para administrar mi jerarquía de vistas y todavía tengo que encontrarme con un problema ya que comencé a hacer las cosas de esta manera. Hay 2 puntos clave:

  • un solo UIViewController se debe usar para administrar el “valor de una pantalla” de su aplicación
  • usa UINavigationController para cambiar vistas

¿A qué me refiero con “valor de una pantalla”? Es un poco vago a propósito, pero en general es una característica o sección de su aplicación. Si tiene algunas pantallas con la misma imagen de fondo pero diferentes superposiciones / ventanas emergentes, etc., debería ser 1 controlador de vista y varias vistas secundarias. Nunca debe encontrarse trabajando con 2 controladores de visualización. Tenga en cuenta que aún puede crear una instancia de UIView en un controlador de vista y agregarlo como una subvista de otro controlador de vista si desea que se muestren ciertas áreas de la pantalla en múltiples controladores de vista.

En cuanto a UINavigationController, ¡este es tu mejor amigo! Desactive la barra de navegación y especifique NO para animated, y tiene una forma excelente de cambiar pantallas a pedido. Puede presionar y abrir los controladores de vista si están en una jerarquía, o puede preparar una matriz de controladores de visualización (incluida una matriz que contiene un solo VC) y configurarla para que sea la stack de vista usando setViewControllers. Esto le da total libertad para cambiar VC, mientras obtiene todas las ventajas de trabajar dentro del modelo esperado de Apple y lograr que todos los eventos, etc., funcionen correctamente.

Esto es lo que hago cada vez que inicio una aplicación:

  • comenzar desde una aplicación basada en la ventana
  • agregue un UINavigationController como rootViewController de la ventana
  • agregue lo que quiera que mi primer UIViewController sea como el controlador raízView del controlador nav

(Tenga en cuenta que comenzar desde la ventana es solo una preferencia personal; me gusta construir cosas por mí mismo, así sé exactamente cómo están comstackdas. Debería funcionar bien con la plantilla basada en vista)

Todos los eventos se activan correctamente y básicamente la vida es buena. A continuación, puede dedicar todo su tiempo a escribir las partes importantes de su aplicación y no perder el tiempo tratando de modificar manualmente las jerarquías de vista en forma.