Aquí es el tono.

  • Tengo un UIViewController subclase que hace algo en su viewWillAppear y viewDidAppear métodos.
  • Quiero nido este punto de vista controlador en un UINavigationViewController.
  • Dependiendo el punto de vista de la jerarquía de la complejidad de los dos métodos viewWillAppear y viewDidAppear de mi controlador no puede ser llamado.

¿Qué debo hacer entonces para asegurarse de que estos dos métodos son llamados siempre, independientemente de mi opinión de la jerarquía?

Ejemplo de un «complejo» de la vista de jerarquía:

UIViewController subclass containing a UITabBarController
     |_ Each tab containing a UINavigationViewController
         |_ Each UINavigationController controller containing a custom UIViewController

Cuando se presente la TabBarController como un modal ver el viewWillAppear y viewDidAppear métodos de la TabBarController son los llamados, pero no las de la costumbre UIViewControllers anidado bajo la UINavigationViewControllers.

OriginalEl autor MiKL | 2011-10-06

4 Comentarios

  1. 21

    NOTA: esto fue escrito en el año 2013. Cambios en el estilo de iOS maneja la vista de las jerarquías de hoy en día pueden hacer que esta solución inútil y/o peligrosos. Así que utilice a su propio riesgo.

    Respuesta Original
    Cuando la anidación de una costumbre UIViewController bajo un UINavigationController los métodos viewWillAppear y viewDidAppear de la costumbre viewController no puede ser llamado, dependiendo de la complejidad de su controlador de vista de la jerarquía (creo modal puntos de vista, controlador de navegación dentro de la pestaña de controlador de vista…). Así que si usted se encuentra en esta situación, ¿qué puede hacer usted para asegurarse de que estos dos métodos son llamados?

    La respuesta…

    Utilizar el UINavigationControllerDelegate métodos

    Esta es una forma muy elegante, el método a aplicar para que no depende de ninguna hipótesis sobre cuando el controlador se puede cargar el controlador de navegación.

    Hay dos métodos disponibles:

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated

    Aquí es cómo el código iba a cambiar.

    Deberá declarar que su CustomViewController implementa la UINavigationControllerDelegate protocolo:

    @interface CustomViewController : UIViewController <UINavigationControllerDelegate>

    Que usted necesita para establecer su CustomViewController como el delegado de la UINavigationController donde se inicializará.

    Último también debe agregar su implementación personalizada de la UINavigationControllerDelegate métodos para su CustomViewController implementación de la clase. Por ejemplo, puede implementar el navigationController:willShowViewController:animated: método, de modo que:

    • cuando el UINavigationController está a punto de mostrar el controlador de vista de sí mismo su viewWillAppear método es llamado
    • cuando el UINavigationController está a punto de mostrar otro punto de vista controlador el delegado de la UINavigationController se establece en este otro punto de vista controlador, siempre que este punto de vista controlador implementa la UINavigationViewControllerDelegate método.

    Elemento de la lista

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if ([viewController isEqual:self]) {
                [viewController viewWillAppear:animated];
        } else if ([viewController conformsToProtocol:@protocol(UINavigationControllerDelegate)]){
                //Set the navigation controller delegate to the passed-in view controller and call the UINavigationViewControllerDelegate method on the new delegate.
                [navigationController setDelegate:(id<UINavigationControllerDelegate>)viewController];
                [[navigationController delegate] navigationController:navigationController willShowViewController:viewController animated:YES];
        }
    }

    Y la navigationController:didShowViewController:animated: puede ser implementado simplemente de la siguiente manera:

    - (void)navigationController:(UINavigationController *)navigationController 
           didShowViewController:(UIViewController *)viewController 
                        animated:(BOOL)animated
    {
        if ([viewController isEqual:self]) {
            [self viewDidAppear:animated];
        }
    }

    El beneficio de este enfoque es realmente que depende exclusivamente de la forma en que el UINavigationViewController se supone que es para trabajar y hacer tus llamadas, justo en el momento adecuado. También permite pasar la delegación alrededor como usted se mueve arriba y abajo de la navegación controlador de la jerarquía de la derecha antes de la viewWillAppear método es llamado.

    Nuevo sencillo de la jerarquía, puede no ser necesario. Pero si alguna vez te encuentras en una situación donde su viewWillAppear y viewDidAppear métodos no son llamados ahora sé qué hacer…

    ¿Tienes una fuente para esta afirmación? Estoy bastante seguro de que estoy usando viewWillAppear en esta situación, y es que se llama. (va a ir y comprobar ahora, aunque!)
    Es particularmente el caso cuando usted comience a jugar con modales de vista de los controladores y más compleja jerarquía. Y la solución sigue siendo genérica: si el método no es llamado, el uso de la UINavigationControllerDelegate protocolo en lugar de llamadas directas
    He hecho mi declaración de un poco menos fuerte, para reflejar el hecho de que si los métodos no son llamados usted puede utilizar la delegación técnica, en lugar de llamadas directas.
    Usted me tenía preocupado ahí por un minuto!
    lo siento… estoy relanzando el problema y la solución, para no asustar a la gente como yo asustado…

    OriginalEl autor MiKL

  2. 8

    Una razón que esto va a suceder es que si reemplazar viewDidAppear: en su UINavigationController subclase y no llamar [super viewDidAppear:animated];

    Que es exactamente. Tantas respuestas sugieren para invocar el viewWillAppear/viewDidAppear manualmente a partir de otro que contiene el controlador. En mi caso, un vistazo más de cerca a estos anula fue suficiente para ver a dónde me olvidé de llamar a la super aplicación.

    OriginalEl autor Dan Rosenstark

  3. 3

    Es 2015 y ahora usted probablemente no necesite utilizar el UINavigationControllerDelegate métodos como en la aceptación de la respuesta. Sólo echa un cuidadosamente su código si usted tiene cualquier error tipográfico o copiar/pegar de error.

    Me encontré con un problema que últimamente viewDidAppear ya no se llama después de algunos copiar/pegar. Después de leer @Yar la respuesta, hice una búsqueda en viewDidAppear en mi código y se encontró que [super viewDidAppear:animated]; fue erróneamente llamado en viewWillAppear:

    -(void)viewWillAppear:(BOOL)animated
    {
       [super viewDidAppear:animated];
       //...      ^^^ 
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        //this is never called :(
    }

    Simplemente compartir este hallazgo en el caso de personas que se ejecute en el mismo problema.

    este es un disparate

    OriginalEl autor Jingshao Chen

  4. 0

    se debe hacer de la siguiente manera:

    Ver (*1) editar

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        CustomViewController *controller = [[CustomViewController alloc] initWithNibName:nil bundle:nil];
        UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
        [controller release];
    
        self.window.rootViewController = navController; //(*1)
        [self.window makeKeyAndVisible];
        [navController release];
        return YES;
    }
    De hecho. Pero este fue un copy/past error. Véase mi respuesta a este problema…
    Ok. Y no CustomViewController aparecen? Si no intentar CustomViewController *controller = [CustomViewController new]; en lugar de CustomViewController *controller = [[CustomViewController alloc] initWithNibName:nil bundle:nil];
    Sí parece bien… Ese no es el punto de la pregunta, sin embargo. El controlador siempre aparece, pero cuando anidado dentro de un UINavigationController la viewWillAppear y viewDidAppear métodos no son llamados.
    Ah ok. En ese caso no sé lo siento :/

    OriginalEl autor mrd3650

Dejar respuesta

Please enter your comment!
Please enter your name here