无法将子视图推入视图控制器

4

我有一个UINavigationController,我有不同的UIView,我使用UISegmentControl在它们之间切换。在切换视图时,我将该视图作为子视图添加到我的导航控制器的视图中:

[self.view addSubview:segmentTab1.view];

并且

[self.view addSubview:segmentTab2.view];

接下来,在子视图中,每个都有一个UITableView,但我的问题是,在didSelectRowAtIndexPath方法中无法推入新的viewController。

该方法被正确调用,并通过设置断点,我可以看到推送视图的方法也被调用了,但什么也没有发生。这是我推送它的代码:

[self.navigationController pushViewController:detailsViewController animated:YES];

我也尝试过

[super.navigationController pushViewController:detailsViewController animated:YES];

我做错了什么 - 或者只是在子视图中无法实现它?

6个回答

6
当你调用-pushViewController方法时,self代表哪个视图控制器?如果在选项卡的子视图中调用该方法,则self可能没有引用添加到顶级视图中的导航控制器。您可以通过从顶级视图内获取导航控制器的内存地址,并将其与子视图中的内容进行比较来验证此问题。显然,如果为nil或不匹配,则这就是你的问题。
只有当导航堆栈本身使用-pushViewController方法添加过后,才能“免费”获得导航控制器,而您的子视图并没有以这种方式添加。

准确地说,调用pushViewController的必须是已经被推入导航控制器的视图。它不一定是最后一个被推入的视图,但它必须在导航控制器的堆栈中。 - Amagrammer
1
澄清: "必须来自视图控制器"——而不是视图。 - Amagrammer
谢谢,Matt。还有“Amagrammer”。我有选项卡,每个选项卡中都有一个带有nib和类的NavigationController。我将设置它,使得每个选项卡都有一个视图控制器,在每个视图控制器中,我添加了一个UINavigationController,该导航控制器可以根据segmentedControl切换其视图,并希望当我到达时能够推入子视图 :) - runmad
基本上,iPhone 上的 App Store 应用程序是我想要实现的一个例子。TabBar,每个都有 UINavigationController,其中包含 segmentedController(至少有一些),并且可以推送行。 - runmad
我同意,当您将子视图添加到现有视图时,它不会包括对导航控制器的引用,您的pushViewController:animated:调用将被发送到nil并被忽略。有趣的是,App Store应用程序(以及其他几个应用程序)似乎使用分段控件来过滤单个nib中的表格数据,而不是作为不同nib之间的选择(基本上是选项卡视图)。 - crafterm
但是你能详细解释一下如何从子视图调用不同的屏幕吗?我正好遇到了这个问题。 - dinesh

2

当我为所有视图实现一个共同的标题时,遇到了类似的问题。经过多次尝试,我通过以下方式解决了这个问题 -

在所有的viewController中

- (void)viewWillAppear:(BOOL)animated {

    [self.view addSubview:[[(NavAppAppDelegate *)[[UIApplication sharedApplication] delegate] headerview] view]];
    [[(NavAppAppDelegate *)[[UIApplication sharedApplication] delegate] headerview] viewWillAppear:YES];

}

我参考了以下帖子来实现标题视图: 在iPhone中多个视图控制器中使用通用XIB
[self.view addSubview:[[(NavAppAppDelegate *)[[UIApplication sharedApplication] delegate] headerview] view]];     // line will load the header subview 

[[(UIApplication sharedApplication] delegate] headerview]的类型是NavAppAppDelegate。在这里,我们可以调用HeaderController的viewWillAppear方法,以检查用户是否已登录并更改登录按钮为注销按钮等等...


1

不是

[self.view addSubview:segmentTab1.view];

并且

[self.view addSubview:segmentTab2.view];

你可以使用

[self pushViewController: segmentTab1 animated: NO];

并且

[self pushViewController: segmentTab2 animated: NO];

要将您的视图控制器添加到导航层次结构中,并使[super.navigationController pushViewController:detailsViewController animated:YES];正常工作。


不确定这是否有效,但如果您在segmentController中切换视图,并且使用TabBar,则点击该视图的tabBarItem将会推回该视图。看起来不太好:( - runmad
我不确定我是否正确理解了这种行为。也许你应该查看navigationController的visibleViewController属性,如果它对应于你要推送的视图,则不要再推送它。 - luvieere

0

如果您不反对使用单例模式,一种可能的方法是将您的产品的UINavigationController对象设置为单例,并从(例如)应用程序委托中访问它。

您可以这样调用它:

[[((MyApplicationDelegate*)[UIApplication delegate]) navController] 
                pushViewController: viewControllerToPush animated: YES];

在MyApplicationDelegate中,navController返回单例对象。


0
LogEntryDetailViewController *leController = [[LogEntryDetailViewController alloc] initWithNibName:@"LogEntryDetailView" bundle:[NSBundle mainBundle]];
    [leController setTitle:[NSString stringWithFormat:@"%@", [logEntriesArray objectAtIndex:row]]];
    [[self navigationController] pushViewController:leController animated:NO];      
    [leController release], leController = nil;

0

我不太清楚你的视图层次结构是什么,但通常情况下,如果你的导航控制器视图不是窗口的第一个子视图或者不是苹果集合视图中的一个元素(另一个导航视图控制器的内容视图或选项卡控制器的内容视图),它就无法正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接