使用多个故事板与TabBarController

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

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

仅仅为了testing目的,我在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.storyboardfind。 在这种情况下,不知道如何实现下面build议的linkView。

这是非常可能的,一个聪明的举动 – 剔除你的故事板,提供更清晰的接口文件来挖掘,减lessXCode的加载时间,更好的组编辑。

我一直在堆栈溢出一段时间,并注意到每个人都诉诸自定义分段或实例化基于选项卡的设置编程。 让人惊讶。 我一起黑了一个简单的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. 一旦加载,它将尝试在其UINavigationController的viewController数组中用Storyboard的初始视图控制器replace它自己。
  3. 当请求时,这个子类将返回故事板的初始视图控制器的UINavigationItem。 这是为了确保加载到UINavigationBars中的导航项目将与交换后的视图控制器相对应。

用法:

要使用它,请将其分配为属于UINavigationController的Storyboard中的UIViewController的子类。

在这里输入图像说明

分配一个恢复ID,你很好去。

在这里输入图像说明

build立:

以下是您如何在故事板中设置它:

显示设置的图表

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

一些胜利在这里:

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

一些限制:

  • 这个子类需要属于链中某个UINavigationController。
  • 这个子类只会实例化Storyboard中的初始视图控制器。 如果你想实例化一个视图控制器,你可以总是将你的Storyboard进一步拆分,并重新应用这个子类的技巧。
  • 推送视图控制器时,这种方法无法正常工作。
  • 用作embedded式视图控制器时,此方法效果不佳。
  • 通过segse传递的消息可能不起作用。 这种方法适用于接口部分是唯一的,不相关的部分(通过模态或通过标签栏)。

这种方法被破解了解决这个UITabBarController问题,所以使用它作为一个更大的问题的部分解决scheme。 我希望苹果改进“多重故事板”的支持。 对于UITabBarController设置,但是,它应该工作。

不知道你的问题是否被回答,并为其他人寻找解决这个问题,请尝试这种方法。

在这里输入图像说明

  1. 使用导航控制器在一个故事板文件中创build选项卡栏控制器。 并添加一个空的视图控制器(我把它命名为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. 解决scheme尚未完成! 您将在SettingsViewController上看到“<Back”作为左侧的navigationItem。 在其viewDidLoad方法中使用以下行:

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

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

这个对我有用。

对于Hawke_Pilot来说这有点晚,但是可能对别人有帮助。

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

但是,这一点不起作用,因为另一个故事板中的收件人不知道它被链接到选项卡栏视图控制器,并且不会显示用于编辑的选项卡栏。 将故事板参考指向所需的视图控制器后,您只需select故事板参考并select编辑器 – >embedded – >导航控制器。 这意味着导航控制器知道它链接到一个标签栏视图控制器,因为它在同一个故事板上,并将显示在底部的标签栏,并允许编辑button图像和标题。 没有要求的代码。

无可否认,这可能不适合每个人,但可能为OP工作。

将以下代码添加到您的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的屏幕截图 截图

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

RBStoryboardLink 。 它的工作对我很好。 让我知道它是否对你有帮助。