【问题标题】:Problems with UINavigationController inside of UITabBarController, viewWillAppear not calledUITabBarController 内的 UINavigationController 问题,未调用 viewWillAppear
【发布时间】:2011-03-05 01:33:39
【问题描述】:

作为概述,每当从堆栈中弹出视图时,我都会遇到 UITabBarController 内的 UINavigationController 调用 viewWillAppear 的问题。

从委托中以编程方式生成一个 UITabBarController:

// Create views for Tab Bar
    UINavigationController *view1   = [[UINavigationController alloc] initWithRootViewController:[[newsFeedNavigationController alloc] initWithStyle:UITableViewStylePlain]];
    resizedTabBatItem *tabBarItem1 = [[resizedTabBatItem alloc] initWithTitle:nil image:[UIImage imageNamed:@"newspaper.png"] tag:0];
    [view1 setTabBarItem:tabBarItem1];
    [tabBarItem1 release];

    UIViewController *view2   = [UIViewController new];
    resizedTabBatItem *tabBarItem2 = [[resizedTabBatItem alloc] initWithTitle:nil image:[UIImage imageNamed:@"speechbubble.png"] tag:1];
    [view2 setTabBarItem:tabBarItem2];
    [tabBarItem2 release];

....

// Create the tab bar controller
    bookTabBarController = [BookTabBarController new];
    [[bookTabBarController view] setFrame:CGRectMake(0, 0, 320, 460)];

    // Add the views to it
    NSArray *viewControllers = [NSArray arrayWithObjects:view1, view2, view3, view4, view5, nil];

    [[bookTabBarController tabBarController] setViewControllers:viewControllers];

我的 newsFeedNavigationController 只是 UITableViewController 的子类(并且子类不会干扰 viewWillAppear,因为它从未在 newsFeedNavigationController 中调用)。在其中,单击时会将新的 UIViewController 推入堆栈的项目。

问题在于,每当视图从堆栈中弹出时,在 newsFeedNavigationController 中永远不会调用 viewWillAppear,并且列表中的项目仍然突出显示。我已经搞砸了几个小时,现在我需要一些帮助来找出我做错了什么。

在我的 newsFeedNavigationController 中,我尝试添加一个 NSLog 以查看它是否被调用或我做了什么,但它甚至从未被调用过。

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"is viewWillAppear called?");
    [super viewWillAppear:animated];
}

编辑:

好的,现在我注意到了一些奇怪的事情:

如果我跑:

[self presentModalViewController:(any UIview) animated:YES];

然后关闭它,viewWillAppear 在弹出和推送视图时开始正常工作......所以现在我很难过。这不是真正的解决方案,但可能是正在发生的事情的内部。

【问题讨论】:

    标签: iphone uinavigationcontroller uitableview viewwillappear


    【解决方案1】:

    为了回答我自己的问题,我发现了问题所在。

    为了遵守 Apple 的“UINavigationController 内没有 UITabBarController”,我编写了自己的标签栏控制器 (bookTabBarController),它基于标准视图控制器。我的问题是该类没有将 viewDidAppear 传递给管理视图控制器的类,因此它永远不知道它是否被显示。

    【讨论】:

    • 我很困惑。在您的帖子中,您说“UITabBarController 中的 UINavigationController”,而在后续文章中,您说“UINavigationController 中的 UITabBarController”……哪个?因为我在将导航控制器作为选项卡栏控制器中的选项卡时遇到了相同的问题......据我所知,应该支持。但是 ViewDidAppear 仅在我从推送到导航控制器的视图之一中呈现模态视图后才开始工作。很奇怪。
    • 查看我的答案以获得该问题的一般解决方案。
    • 这和我的问题一样。很抱歉造成混淆。我最初拥有的是一个带有视图控制器的 UINavigationController,然后“主”屏幕将包含堆栈中下一个本质上是 UITabBarController 的内容。然后,您可以将新视图推送到堆栈中。例如:UINavigationController 以 root 身份登录视图,当进入时,一个 uitabbar 被推入,并且来自表的视图可以被推入“主”导航。我的问题是 viewWillAppear 没有被传递到堆栈中(它会从 UINavigationController 传递到 UITabBarController,但不会传递到 Tab Bar 的视图)。
    • 你能添加显示如何解决这个问题的代码吗?
    • @Brabbeldas - 自从我提出这个问题以来,Apple 已经向 UIViewController 引入了 View Containment API,这减轻了管理子视图响应的大部分工作。如果您想滚动自己的标签栏控制器(或包含其他视图的任何视图),那么请朝那个方向寻找最有效的解决方案
    【解决方案2】:

    另一种解决方案是设置导航控制器的委托。在委托中,实现以下方法:

    - (void)navigationController:(UINavigationController *)navigationController  willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [viewController viewWillAppear:animated];
    }
    

    这将确保 viewWillAppear 将在其视图即将出现在导航控制器中的任何视图控制器上被调用。如果你这样做,viewWillAppear 都会被调用,无论视图是因为被推送而出现,还是因为子视图被弹出而出现。

    【讨论】:

    • 不幸的是,我尝试了这种方法,但没有奏效。嗯,它确实有效,但它没有。问题在于,即使调用了 viewWillAppear:animated,它也没有被传递到选项卡栏中包含的子视图,因为它没有在选项卡栏的 viewWillAppear 中被显式调用。但对于其他遇到问题的人来说,这是一个潜在的解决方案。但是,如果 viewWillAppear:animated 不起作用,则可能意味着其他问题(如我的情况)。
    【解决方案3】:

    解决这个问题的方法是让包含 UINavigationController 的 UIViewController 将所需的消息传递给它。 UINavigationController 会将消息转发到适当的视图控制器。这似乎违反直觉,但确实有效。

    @interface NavigationWrapperViewController : UIViewController {
        // navigationController must be a subview of this view controller's view
        UINavigationController *navigationController;
    }
    @property (nonatomic, assign) UINavigationController *navigationController;
    @end
    
    @implementation NavigationWrapperViewController
    @synthesize navigationController;
    
    -(void)viewWillAppear:(BOOL)animated {
        [navigationController viewWillAppear:animated];
    }
    -(void)viewDidAppear:(BOOL)animated {
        [navigationController viewDidAppear:animated];
    }
    -(void)viewWillDisappear:(BOOL)animated {
        [navigationController viewWillDisappear:animated];
    }
    -(void)viewDidDisappear:(BOOL)animated {
        [navigationController viewDidDisappear:animated];
    }
    
    @end

    您可以在Pastebin(我没有发布)上找到更完整的解决方案。

    感谢davidbenini.itjaekwon 提供此解决方案。

    【讨论】:

    • 这个解决方案有点不完整,粘贴箱链接有点语法混乱,但如果这不能解决我的问题,我会被诅咒的!你摇滚!
    【解决方案4】:

    一个更简单的技巧:

    UITabBarController 的子类中,重写:

    -(void)loadView{
    
        [super loadView];
    
        //here goes the trick:
        [self setSelectedIndex:1];
        [self setSelectedIndex:0];
    }
    

    【讨论】:

    • 这个变通办法帮助了我,但我发现立即将索引设置回 0 不起作用。我不得不等到 viewDidAppear。另一个页面不显示或闪烁并且可以工作,因为首先手动选择另一个选项卡意味着有问题的视图可以工作。需要注意的是,您设置的索引必须包含一个非常简单的页面。我最初尝试了一个带有子视图的视图,子视图消失了,但仍然可以进行用户交互,即问题转移到了该选项卡。
    【解决方案5】:

    好的,这很旧,很旧,但我最终遇到了类似的问题。

      UITabViewController
         UINavigationController
           UITableViewController1
             UITableViewController2
    

    当弹出UITableViewController2 时,UITableViewController1 中的viewWillAppear 函数从未被调用。

    问题:我的UITabViewController 自定义类在没有调用超级实现的情况下覆盖了viewWillAppear

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2015-10-09
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多