跨子视图控制器从UITabBarController继承/保留UINavigationBar?

时间:2014-01-30 03:10:20

标签: objective-c cocoa-touch uitabbarcontroller uinavigationbar

我创建了一个UITabBarController,其中包含多个UIViewControllers作为其标签。我还希望在此UINavigationBar中显示一个常量UITabBarController,它将持续显示在标签页上。由于UITabBarController的子视图控制器都不是UINavigationControllers,我希望这是可能的,不会引起冲突。有没有办法做到这一点?

目前我正在为每个子视图控制器复制粘贴完全相同的UINavigationBar和相应的逻辑,因此我猜测有更好的方法。

就这为何有用而言:想象一下UINavigationBar包含两个UIBarButtonItems用于“退出”和“帐户”。按“注销”会将您注销并推送模态视图控制器,以便您可以重新登录,而按“帐户”则会显示一个带有您的帐户信息的模态视图控制器。

我在Stack Overflow上找到了这个现有的问题,但问题本身及其评论的措辞都非常缺乏且没有信息:How to add a navigation bar to UITabBarController?


更新

我有一种感觉,我可能不会很好地解释自己,所以我创建了一个图形来说明我想要做的事情。在下面的图片中,我有一个UITabBarController模型,其中有四个UIViewController s作为子项。我希望有一个恒定的UINavigationBar,以便用户可以按Done来关闭模态显示的视图控制器。由于每个子视图控制器都是单个视图,因此为了使UINavigationController出现,似乎没有必要将每个子视图控制器嵌入其自己的UINavigationBar中。目前,当UITabBarController以模态方式显示时,不会出现导航栏。

Visualization of desired UITabBarController with UINavigationBar and child UIViewControllers

3 个答案:

答案 0 :(得分:3)

我终于开始工作了!!

简而言之:您无法继承或保留UINavigationBar,但您可以通过其UIBarButtonItem设置其UINavigationItem

这是我所做的,其次是相关代码,然后是警告:

我做了什么:

1)子类UITabBarController :我创建了自己的UITabBarController自定义子类。由于我希望我的两个UIBarButtonItem在标签中保持不变,因此我还在@property子类中创建了UITabBarController s。由于我也希望我的UITabBarController能够处理这些UIBarButtonItem,因此我还为UITabBarController子类中的每个按钮创建了一个方法。

2)在UINavigationControllers中为选项卡嵌入视图控制器:即使您不想要或不需要UINavigationController,这也是获得所需效果的最佳方式,因为在iOS 7中导航栏在状态栏下方向上延伸到屏幕顶部。 (据我所知,我无法使用UINavigationBar而不是UINavigationController在iOS 7中复制此效果。)

3)将UIBarButtonItems分配给顶级视图控制器:我从我的UIBarButtonItem子类中将UITabBarController分配给我的标签栏控制器{{1}中的所需视图控制器}和-[initWithNibName:bundle:]方法。我通过-[awakeFromNib]遍历我的标签栏控制器中指定为选项卡的所有视图控制器来完成此操作;检查它们是否self.viewControllers;并通过UINavigationControllerUIBarButtonItem将我的[navigationController.topViewController.navigationItem setLeftBarButtonItem:self.leftBarButton]分配给导航控制器的顶视图控制器导航项。

相关守则:

[navigationController.topViewController.navigationItem setRightBarButtonItem:self.RightBarButton]

注意事项:

在达到我的解决方案的过程中,我学到了很多东西,包括以下内容:

  • 您无法以编程方式设置自己的UINavigationBar。最多可以创建自己的自定义// MyTabBarController.h // @interface MyTabBarController () <UITabBarControllerDelegate> @property (nonatomic, strong) UIBarButtonItem *leftBarButton; @property (nonatomic, strong) UIBarButtonItem *rightBarButton; - (void)setup; - (void)buttonLeft:(UIBarButtonItem *)sender; - (void)buttonRight:(UIBarButtonItem *)sender; @end @implementation MyTabBarController @synthesize leftBarButton = _leftBarButton; @synthesize rightBarButton = _rightBarButton; - (UIBarButtonItem *)leftBarButton { if (!_leftBarButton) _leftBarButton = [[UIBarButtonItem alloc] initWithTitle:@"Left" style:UIBarButtonItemStyleBordered target:self action:@selector(buttonLeft:)]; return _leftBarButton; } - (UIBarButtonItem *)rightBarButton { if (!_rightBarButton) _rightBarButton = [[UIBarButtonItem alloc] initWithTitle:@"Right" style:UIBarButtonItemStyleBordered target:self action:@selector(buttonRight:)]; return _rightBarButton; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { [self setup]; } return self; } - (void)awakeFromNib { [self setup]; } - (void)setup { [self setDelegate:self]; // since I am using myself as the UITabBarControllerDelegate for (UIViewController *viewController in self.viewControllers) { if ([viewController isKindOfClass:[UINavigationController class]]) { UINavigationController *navigationController = (UINavigationController *)viewController; [navigationController.topViewController.navigationItem setLeftBarButtonItem:self.leftBarButton]; [navigationController.topViewController.navigationItem setRightBarButtonItem:self.rightBarButton]; } } } - (void)buttonLeft:(UIBarButtonItem *)sender { // Left bar button action } - (void)buttonRight:(UIBarButtonItem *)sender { // Right bar button action } @end 子类,并通过Interface Builder / Storyboard将其设置为UINavigationBar正如here (external website: iOS Dev Notes)所述。
  • 您无法创建和使用XIB中的UINavigationBar ,如下所述:How to customize UINavigationBar with XIB?
  • 通过将UINavigationBar和UITabBar拖入到UIViewController中将组合的“UITabBarController / UINavigationController”混合在iOS 7中无效,因为iOS 7使用重叠的半透明UI元素,其重叠不能以编程方式设置好(例如,状态栏后面的导航栏的扩展名)。
  • 在UINavigationController中嵌入UITabBarController是可行的,但Apple的文档明确禁止/禁止这样做。这是因为嵌入顶级导航功能(即允许用户使用的UITabBarController)是错误的逻辑在应该能够推送和弹出其视图控制器的UI中切换并行接口。

答案 1 :(得分:0)

好的,这是一所古老的学校,但这就是我所做的。

首先,我创建了一个Nib来保持标签栏控制器。我这样做是通过创建一个空的Nib并将标签栏控制器拖入其中作为第一项。标签栏控制器预先填充了两个视图控制器。这些可以删除。

接下来,将所需的所有导航控制器拖入标签栏控制器。您应该小心它们是标签栏控制器的子项,而不是标签栏控制器的兄弟。

导航控制器预先填充了视图控制器。对于每个视图控制器,选择视图控制器。在“属性”检查器中,为视图控制器设置NIB名称到NIB(或者可以在“标识”检查器中设置“自定义类”)。

最后,在-application:didFinishLaunchingWithOptions:中加载标签栏控制器。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"JLTRootController" owner:nil options:nil];
    UIViewController *controller = views[0];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.window.backgroundColor = [UIColor whiteColor];
    self.window.rootViewController = controller;
    [self.window makeKeyAndVisible];
    return YES;
}

希望有所帮助

答案 2 :(得分:0)

我知道这个帖子已经开始并且很久以前就回答了,但我认为我会贡献一个宝石:

  • 在UITabBarController之前将故障板中的UINavigationController添加到故事板中。按住Control键并拖动以将UITabBarController设置为其根视图控制器。这个UINavigationController将作为顶部的持久导航栏。
  • 对于每个选项卡,将UINavigationController设置为tabbar的视图控制器,并将现有视图控制器链接为其根视图控制器。
  • 对于每个标签,请进入UINavigationController的设置,然后取消选中“显示导航栏&#39;”框。这将隐藏内部导航栏。

你现在在顶部有一个持久性栏(由UITavBartController之前的UINavigationController控制),而不是在故事板中编写任何代码:)。您甚至可以将按钮拖到它上面以及自定义标题视图。

如果您想以编程方式访问此内容:

  • 您可以继承UITabBarController。然后self.navigationItem.rightBarButton应该允许您轻松访问和设置按钮。
  • 您也可以使用`self.tabbarcontroller.navigationitem.rightBarButton&#39;直接从标签视图控制器设置它。所以这是间接的一点点。

简单! 这个答案是基于我以前的一个答案,如果您想了解更多细节和图片,可以在这里查看: how iphone facebook app make the navigation bar fixed