7

作为概述,每当从堆栈中弹出视图时,我都会遇到 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 在弹出和推送视图时开始正常工作......所以现在我很难过。这不是一个真正的解决方案,但可能是正在发生的事情的内部。

4

5 回答 5

1

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

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

于 2010-06-19T21:21:10.733 回答
1

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

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

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

于 2010-06-28T00:39:19.960 回答
1

解决此问题的方法是让包含 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的解决方案。

于 2010-09-20T19:02:10.780 回答
1

一个更简单的技巧:

在你的子类中UITabBarController,覆盖这个:

-(void)loadView{

    [super loadView];

    //here goes the trick:
    [self setSelectedIndex:1];
    [self setSelectedIndex:0];
}
于 2012-09-19T03:01:32.763 回答
0

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

  UITabViewController
     UINavigationController
       UITableViewController1
         UITableViewController2

从 中弹出时,从未调用过inUITableViewController2viewWillAppear函数。UITableViewController1

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

于 2016-07-19T01:51:20.590 回答