首页 文章

使用UINavigationController时,不调用我的控制器的viewWillAppear或viewDidAppear方法

提问于
浏览
13

这是球场 .

  • 我有一个UIViewController子类,它在viewWillAppear和viewDidAppear方法中做了一些事情 .

  • 我想将此视图控制器嵌套在UINavigationViewController中 .

  • 根据视图层次结构的复杂性,可能无法调用我的控制器的两个方法 viewWillAppearviewDidAppear .

那么我应该怎么做以确保无论我的视图层次结构如何都始终调用这两个方法?

“复杂”视图层次结构的示例:

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

当您将TabBarController呈现为模态视图时,将调用TabBarController的 viewWillAppearviewDidAppear 方法,但不会调用嵌套在UINavigationViewControllers下的自定义UIViewControllers方法 .

4 回答

  • 21

    NOTE: this was written in 2013. Changes to the way iOS handles view hierarchies nowadays may render this solution useless and/or dangerous. So use at your own risk.

    Original Answer 在UINavigationController下嵌套自定义UIViewController时,可能无法调用自定义viewController的方法viewWillAppear和viewDidAppear,具体取决于视图控制器层次结构的复杂程度(想想模态视图,选项卡视图控制器内的导航控制器......) . 因此,如果您发现自己处于这种情况,您可以做些什么来确保调用这两种方法?

    答案...

    使用UINavigationControllerDelegate方法

    这是一种非常优雅的实现方法,因为它不依赖于关于导航控制器何时加载控制器的任何假设 .

    有两种方法可供选择:

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

    以下是代码的更改方式 .

    您需要声明您的CustomViewController实现UINavigationControllerDelegate协议:

    @interface CustomViewController : UIViewController <UINavigationControllerDelegate>
    

    您需要将CustomViewController设置为初始化它的UINavigationController的委托 .

    最后,您还必须将UINavigationControllerDelegate方法的自定义实现添加到CustomViewController类实现中 . 例如,您可以实现 navigationController:willShowViewController:animated: 方法,以便:

    • 当UINavigationController即将显示视图控制器本身时,将调用viewWillAppear方法

    • 当UINavigationController即将显示另一个视图控制器时,UINavigationController的委托被设置为该另一个视图控制器,前提是该视图控制器实现了UINavigationViewControllerDelegate方法 .

    项目清单

    - (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];
        }
    }
    

    navigationController:didShowViewController:animated: 可以简单地实现如下:

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

    这种方法的好处实际上是你完全依赖于UINavigationViewController应该工作的方式,并且你在恰当的时间拨打电话 . 它还允许您在调用viewWillAppear方法之前向上和向下移动导航控制器层次结构时传递委托 .

    同样对于简单的层次结构,可能不需要这样 . 但是如果你发现自己处于没有调用 viewWillAppearviewDidAppear 方法的情况下,你现在知道该怎么做了......

  • 3

    这种情况发生的一个原因是,如果你在 UINavigationController 子类中覆盖 viewDidAppear: 并且不调用 [super viewDidAppear:animated]; ...

  • 8

    现在是2015年,您可能不需要像接受的答案那样使用UINavigationControllerDelegate方法 . 如果您有任何拼写错误或复制/粘贴错误,请检查 carefully 您的代码 .

    我最近遇到了一个问题,即在复制/粘贴后不再调用 viewDidAppear . 在阅读@ Yar的回答后,我在我的代码中对 viewDidAppear 进行了搜索,发现在 viewWillAppear 中错误地调用了 [super viewDidAppear:animated];

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

    如果人们遇到同样的问题,请在这里分享这个发现 .

  • 0

    它应该做如下:

    见(* 1)编辑

    - (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;
    }
    

相关问题