使用带有TabBarController的多个故事板 [英] Using multiple storyboards with a TabBarController
问题描述
好的,所以在开发我的最新应用程序的过程中,我发现我的故事板
变得很大,所以为了清理它,我把它分开了进入多个故事板
,然后失控。仅仅为了设置我有大约20 tableviewcontrollers
从根 NavigationController
分支出来。那个 navigationcontroller
是 TabBarController
上的一个TabItem,它是应用程序的
根视图控制器。
Okay, so in the process of developing my newest app, I found that my storyboard
got huge, so in an effort to clean it up some, i have divided it into multiple storyboards
before it gets out of hand. just for settings alone i have roughly 20 tableviewcontrollers
that branch out from a root NavigationController
. That navigationcontroller
was a TabItem on a TabBarController
, which is the application's
root view controller.
我已将 TabBar
移动到它自己的 StoryBoard
作为 Root_Storyboard
,导航控制器现在是Settings_Storyboard的初始视图。
I've moved the TabBar
into it's own StoryBoard
as the Root_Storyboard
and the Navigation controller is now the initial view of the Settings_Storyboard.
仅用于测试目的,我在 TabBarController
(Root_Storyboard)中添加了一些 UIViewControllers
作为标签项,并将其子类化为一个,并将以下代码添加到其中 viewWillAppear
方法。它工作得很好,但我知道 presentViewController
以模态方式显示 NavigationController
并隐藏 tabBar
。显然我不想那样,我如何让它正确推送,以便 TabBar
仍然可见?
Just for testing purposes, I placed a few UIViewControllers
as tab items in the TabBarController
(Root_Storyboard) and subclassed one and added the following code to it's viewWillAppear
method. It works great, but I know that the presentViewController
displays the NavigationController
modally and hides the tabBar
. Obviously I don't want that, how do I get it to push properly so that the TabBar
remains visible?
- (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(UITabBarController的子代:index(1))
的子类方法。我试图加载的 UINavigationController / UITableViewController
可以在 Settings_iPhone.storyboard
中找到。在这种情况下,不确定如何实现下面建议的linkView。
Edit - To clarify. The above code is the subclassed method for a UIViewController (child of UITabBarController:index(1))
in the Root_iPhone.storyboard. The UINavigationController/UITableViewController
that I am trying to load is found in Settings_iPhone.storyboard
. Not sure how to implement the linkView suggested below in this situation.
推荐答案
这很可能也是一个聪明的举动 - 整理你的故事板提供更清晰的界面文件,以便深入挖掘,减少XCode中的加载时间,以及更好的组编辑。
This is quite possible and a smart move - decluttering your Storyboards presents cleaner interface files to dig through, reduced loading times in XCode, and better group editing.
我已经在Stack Overflow上梳理了一段时间并注意到每个人都在求助自定义Segues或以编程方式实例化基于选项卡的设置。让人惊讶。我已经破解了一个简单的UIViewController子类,您可以将其用作故事板的占位符。
I've been combing across Stack Overflow for a while and noticed everyone is resorting to Custom Segues or instantiating tab based setups programmatically. Yikes. I've hacked together a simple UIViewController subclass that you can use as a placeholder for your storyboards.
代码:
头文件:
#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
描述:
- 视图控制器使用其恢复标识符来实例化项目中的故事板。
- 一旦加载,它将尝试使用Storyboard的
初始视图控制器在其
UINavigationController的viewController数组中替换自身。 - 如果需要,此子类将返回Storyboard初始视图控制器的UINavigationItem。这是为了确保加载到UINavigationBars中的导航项在交换后对应于视图控制器。
用法:
要使用它,请将它指定为属于UINavigationController的Storyboard中的UIViewController的子类。
To use it, assign it as the subclass of a UIViewController in your Storyboard that belongs to a UINavigationController.
分配一个恢复身份证,你很高兴。
Assign it a Restoration ID, and you're good to go.
设置:
以下是您的看法在故事板中设置:
And here's how you set it up in the Storyboard:
此设置显示一个标签栏控制器,其中导航控制器作为其第一个标签控制器。每个导航控制器都有一个简单的UIViewController作为其根视图控制器(我已经将UIImageViews添加到占位符,以便于记住它链接到的内容)。它们中的每一个都是TVStoryboardViewController的子类。每个都有一个恢复ID设置到他们应该链接到的故事板。
This setup shows a tab bar controller with navigation controllers as its first tab controllers. Each navigation controller has a simple UIViewController as its root view controller (I've added UIImageViews to the placeholders to make it easy to remember what it links to). Each of them is a subclass of TVStoryboardViewController. Each has a Restoration ID set to the storyboard they should link to.
这里有些胜利:
- 它似乎最适用于模式演示,其中子类是导航控制器的根视图控制器。
- 子类不推堆栈上的任何控制器 - 它交换。这意味着您不必手动隐藏后退按钮或覆盖其他地方的标签行为。
- 如果双击选项卡,它将带您进入Storyboard的初始视图,如预期(你不会再看到那个占位符了。)
- 设置起来非常简单 - 没有自定义segues或设置多个子类。
- 你可以添加UIImageViews以及你喜欢的任何占位符视图控制器,使你的故事板更清晰 - 它们永远不会显示。
- It seems to work best for modal presentations where the subclass is the root view controller of a navigation controller.
- The subclass doesn't push any controllers on the stack - it swaps. This means you don't have to manually hide a back button or override tab behaviour elsewhere.
- If you double tap on a tab, it will take you to the Storyboard's initial view, as expected (you won't see that placeholder again).
- Super simple to set up - no custom segues or setting multiple subclasses.
- You can add UIImageViews and whatever you like to the placeholder view controllers to make your Storyboards clearer - they will never be shown.
一些限制:
- 此子类需要属于链中某处的UINavigationController。
- 此子类仅实例化Storyboard中的初始视图控制器。如果你想在链中进一步实例化一个视图控制器,你可以随时拆分你的故事板并重新应用这个子类技巧。
- 这种方法在推送视图控制器时效果不佳。
- 这种方法在用作嵌入式视图控制器时效果不佳。
- 通过segue传递的消息可能无法正常工作。这种方法适用于界面部分是唯一的,不相关的部分(以模态或通过标签栏显示)的设置。
- This subclass needs to belong to a UINavigationController somewhere in the chain.
- This subclass will only instantiate the initial view controller in the Storyboard. If you want to instantiate a view controller further down the chain, you can always split your Storyboards further and reapply this subclass trick.
- This approach doesn't work well when pushing view controllers.
- This approach doesn't work well when used as an embedded view controller.
- Message passing via segues likely won't work. This approach suits setups where sections of interface are unique, unrelated sections (presented modally or via tab bar).
这种方法被黑了要解决这个UITabBarController问题,请将其用作更大问题的部分解决方案。我希望Apple能够改进多故事板支持。但是对于UITabBarController设置,它应该是一种享受。
This approach was hacked up to solve this UITabBarController problem, so use it as a partial solution to a bigger issue. I hope Apple improves on 'multiple storyboard' support. For the UITabBarController setup however, it should work a treat.
这篇关于使用带有TabBarController的多个故事板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!