繁体   English   中英

使用带有TabBarController的多个故事板

[英]Using multiple storyboards with a TabBarController

好吧,所以在开发我的最新应用程序的过程中,我发现我的storyboard变得庞大,所以为了清理它,我把它分成multiple storyboards然后才失控。 仅仅为了设置我有大约20个tableviewcontrollers从根NavigationController分支出来。 那个navigationcontrollerTabBarController上的一个TabItem,它是application's根视图控制器。

我已将TabBar移动到它自己的StoryBoard作为Root_Storyboard ,导航控制器现在是Settings_Storyboard的初始视图。

仅出于测试目的,我在TabBarController (Root_Storyboard)中放置了一些UIViewControllers作为选项卡项,并将其子类化为一个,并将以下代码添加到它的viewWillAppear方法中。 它工作得很好,但我知道presentViewController以模态presentViewController显示NavigationController并隐藏tabBar 显然我不想那样,我怎样才能让它正确推动以便TabBar保持可见?

- (void) viewWillAppear:(BOOL)animated {
UIStoryboard *settingsStoryboard = [UIStoryboard storyboardWithName:@"Settings_iPhone" bundle:nil];
UIViewController *rootSettingsView = [settingsStoryboard instantiateInitialViewController];

[self.tabBarController presentViewController:rootSettingsView animated:NO completion:NULL];
}

编辑 - 澄清。 上面的代码是Root_iPhone.storyboard中UIViewController (child of UITabBarController:index(1))的子类方法。 我试图加载的UINavigationController/UITableViewController可以在Settings_iPhone.storyboard找到。 在这种情况下,不确定如何实现下面建议的linkView。

这是非常可能的,一个聪明的举动 - 整理你的故事板提供了更清晰的界面文件,可以深入挖掘,减少XCode的加载时间,以及更好的组编辑。

我已经在Stack Overflow上梳理了一段时间,并注意到每个人都采用自定义分段或以编程方式实例化基于选项卡的设置。 让人惊讶。 我已经破解了一个简单的UIViewController子类,您可以将其用作故事板的占位符。

码:

头文件:

#import <UIKit/UIKit.h>

@interface TVStoryboardViewController : UIViewController

@end

实施文件:

#import "TVStoryboardViewController.h"



@interface TVStoryboardViewController()

@property (nonatomic, strong) UIViewController *storyboardViewController;

@end



@implementation TVStoryboardViewController



- (Class)class { return [self.storyboardViewController class]; }

- (UIViewController *)storyboardViewController
{
    if(_storyboardViewController == nil)
    {

        UIStoryboard *storyboard = nil;
        NSString *identifier = self.restorationIdentifier;

        if(identifier)
        {
            @try {
                storyboard = [UIStoryboard storyboardWithName:identifier bundle:nil];
            }
            @catch (NSException *exception) {
                NSLog(@"Exception (%@): Unable to load the Storyboard titled '%@'.", exception, identifier);
            }
        }

        _storyboardViewController = [storyboard instantiateInitialViewController];
    }

    return _storyboardViewController;
}

- (UINavigationItem *)navigationItem
{
    return self.storyboardViewController.navigationItem ?: [super navigationItem];
}

- (void)loadView
{
    [super loadView];

    if(self.storyboardViewController && self.navigationController)
    {
        NSInteger index = [self.navigationController.viewControllers indexOfObject:self];

        if(index != NSNotFound)
        {
            NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
            [viewControllers replaceObjectAtIndex:index withObject:self.storyboardViewController];
            [self.navigationController setViewControllers:viewControllers animated:NO];
        }
    }
}

- (UIView *)view { return self.storyboardViewController.view; }



@end

描述:

  1. 视图控制器使用其恢复标识符来实例化项目中的故事板。
  2. 加载后,它将尝试使用Storyboard的初始视图控制器在其UINavigationController的viewController数组中替换自身。
  3. 请求时,此子类将返回Storyboard的初始视图控制器的UINavigationItem。 这是为了确保加载到UINavigationBars中的导航项与交换后的视图控制器相对应。

用法:

要使用它,请将它指定为属于UINavigationController的Storyboard中的UIViewController的子类。

在此输入图像描述

为它分配一个恢复ID,你很高兴。

在此输入图像描述

建立:

以下是您在Storyboard中设置的方式:

图显示设置

此设置显示标签栏控制器,其中导航控制器作为其第一个标签控制器。 每个导航控制器都有一个简单的UIViewController作为其根视图控制器(我已经将UIImageViews添加到占位符中,以便于记住它链接到的内容)。 它们中的每一个都是TVStoryboardViewController的子类。 每个都有一个恢复ID设置为他们应链接到的故事板。

有些胜利:

  • 它似乎最适用于模态演示,其中子类是导航控制器的根视图控制器。
  • 子类不会推送堆栈上的任何控制器 - 它交换。 这意味着您不必手动隐藏后退按钮或覆盖其他位置的选项卡行为。
  • 如果您双击选项卡,它将按照预期将您带到Storyboard的初始视图(您将不会再次看到该占位符)。
  • 设置超级简单 - 没有自定义segues或设置多个子类。
  • 您可以将UIImageViews和您喜欢的任何内容添加到占位符视图控制器中,以使您的故事板更清晰 - 它们永远不会显示。

一些限制:

  • 该子类需要属于链中某处的UINavigationController。
  • 此子类仅实例化Storyboard中的初始视图控制器。 如果要在链中进一步实例化视图控制器,可以始终进一步拆分故事板并重新应用此子类技巧。
  • 推送视图控制器时,此方法无法正常工作。
  • 当用作嵌入式视图控制器时,此方法不能很好地工作。
  • 通过segue传递的消息可能不起作用。 这种方法适合于界面部分是唯一的,不相关的部分(以模态或通过标签栏呈现)的设置。

这种方法被黑客攻击以解决这个UITabBarController问题,因此将其用作更大问题的部分解决方案。 我希望Apple能够改进“多故事板”支持。 但是对于UITabBarController设置,它应该是一种享受。

对于Hawke_Pilot来说这有点晚了,但它可能对其他人有所帮助。

从iOS 9.0开始,您可以创建一个关系Segue到另一个故事板。 这意味着标签栏视图控制器可以链接到另一个故事板上的视图控制器,而不会在其他答案中看到一些令人费解的技巧。 :-)

但是,仅此一点无济于事,因为其他故事板中的收件人不知道它被链接到选项卡栏视图控制器,并且不会显示选项卡栏进行编辑。 将Storyboard参考指向所需的View Controller后,您只需选择Storyboard Reference并选择Editor-> Embed In-> Navigation Controller。 这意味着导航控制器知道它链接到标签栏视图控制器,因为它位于同一个故事板上,并将在底部显示标签栏并允许编辑按钮图像和标题。 无需代码。

不可否认,这可能不适合所有人,但可能会为OP工作。

不确定您的问题是否得到解答,并且对于寻找此问题的解决方案的其他人,请尝试此方法。

在此输入图像描述

  1. 在一个故事板文件中创建带有导航控制器的选项卡栏控制器。 并添加一个空视图控制器(我将其命名为RedirectViewController),如图所示。
  2. 子视图控制器(我们称之为SettingsViewController为您的案例)位于Settings_iPhone.storyboard中。
  3. 在RedirectViewController.m中,代码为:

     - (void)viewWillAppear:(BOOL)animated { UIStoryboard *settingsStoryboard = [UIStoryboard storyboardWithName:@"Settings_iPhone" bundle:nil]; UIViewController *rootSettingsView = [settingsStoryboard instantiateInitialViewController]; [self.navigationController pushViewController:rootSettingsView animated:NO completion:nil]; } 
  4. 触摸“设置”选项卡后,SettingsViewController将立即进入视图。
  5. 解决方案尚未完成! 您将在SettingsViewController上看到“<Back”作为左侧navigationItem。 viewDidLoad方法中使用以下行:

     self.navigationItem.hidesBackButton = YES; 
  6. 此外,为了防止相同的标签栏项被轻击并导致跳回到空白的rootViewController,目标视图控制器将需要实现UITabBarControllerDelegate

     - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController { return viewController != tabBarController.selectedViewController; } 

这个对我有用。

将以下代码添加到LinkViewController

-(void) awakeFromNib{
    [super awakeFromNib];
    ///…your custom code here ..

    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:self.storyBoardName bundle:nil];
    UIViewController * scene = nil;

    // Creates the linked scene.
    if ([self.sceneIdentifier length] == 0)
        scene = [storyboard instantiateInitialViewController];
    else
        scene = [storyboard instantiateViewControllerWithIdentifier:self.sceneIdentifier];
        if (self.tabBarController)
            scene.tabBarItem = self.tabBarItem;
    }

这是LinkViewController的screenShot 截图

LinkViewController只是一个占位符,可以放置新的viewController。 这是我用于我的应用程序的示例代码。

RBStoryboardLink 它对我很有用。 如果它对您有帮助,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM