使用带有TabBarController的多个故事板

Haw*_*lot 8 iphone objective-c storyboard uitabbarcontroller ios

好吧,所以在开发我的最新应用程序的过程中,我发现我的应用程序storyboard非常庞大,所以为了清理一些应用程序,我已经把它分成了multiple storyboards它.仅仅为了设置,我有大约20 tableviewcontrollers个从根分支出来NavigationController.那navigationcontroller是一个TabItem TabBarController,它是一个application's根视图控制器.

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

仅出于测试目的,我UIViewControllersTabBarController(Root_Storyboard)和子类中放置了一些标签项,并将以下代码添加到它的viewWillAppear方法中.它工作得很好,但我知道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];
}
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*eek 10

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

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

码:

头文件:

#import <UIKit/UIKit.h>

@interface TVStoryboardViewController : UIViewController

@end
Run Code Online (Sandbox Code Playgroud)

实施文件:

#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
Run Code Online (Sandbox Code Playgroud)

描述:

  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设置,它应该是一种享受.


Row*_*nPD 6

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

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

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

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


Ric*_*ick 5

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

在此输入图像描述

  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];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 触摸设置选项卡时,SettingsViewController将立即被推入视图.
  5. 解决方案尚未完成!您将在SettingsViewController上看到"<Back"作为左侧navigationItem.在其viewDidLoad方法中使用以下行:

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

    - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController 
    {
        return viewController != tabBarController.selectedViewController;
    }
    
    Run Code Online (Sandbox Code Playgroud)

这个对我有用.


Pri*_*wal 2

将以下代码添加到您的 LinkViewController

\n\n
-(void) awakeFromNib{\n    [super awakeFromNib];\n    ///\xe2\x80\xa6your custom code here ..\n\n    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:self.storyBoardName bundle:nil];\n    UIViewController * scene = nil;\n\n    // Creates the linked scene.\n    if ([self.sceneIdentifier length] == 0)\n        scene = [storyboard instantiateInitialViewController];\n    else\n        scene = [storyboard instantiateViewControllerWithIdentifier:self.sceneIdentifier];\n        if (self.tabBarController)\n            scene.tabBarItem = self.tabBarItem;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是 LinkViewController 的屏幕截图截屏

\n\n

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

\n\n

RBStoryboardLink。它对我来说非常有用。让我知道这是否对您有帮助。

\n