在应用程序启动时从故事板中选择备用第一视图控制器

时间:2012-05-31 03:16:52

标签: iphone ios5 storyboard

我刚刚开始使用iOS编程,到目前为止,我在这里找到的教程和答案对于前进起了很大的帮助。然而,这个特殊问题一直困扰着我,我无法找到“感觉正确”的答案。

我正在编写一个连接到远程服务的应用程序,用户需要先登录才能使用它。当他们开始使用应用程序时,他们的第一个视图应该是登录对话框;当他们之前进行身份验证时,他们会立即看到概述页面。

该项目使用故事板 - 我认为这是一个很棒的功能 - 因此大多数选择和加载根视图控制器的代码已经处理好了。我认为添加逻辑的最佳位置是application:didFinishLaunchingWithOptions:

AppDelegate方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
      (NSDictionary *)launchOptions
{
    // select my root view controller here based on credentials present or not
    return YES;
}

但这提出了两个问题:

  1. 在此特定委托方法中,已根据故事板选择(并加载?)根视图控制器。我可以移动到加载过程中的早期位置来覆盖第一个视图控制器选择,还是会使问题不必要地复杂化?

  2. 要覆盖第一个视图控制器,我需要对故事板的引用,但我找不到比使用storyboardWithName:bundle:的{​​{1}}构造函数更好的方法。这感觉不对,应用程序应该已经引用了故事板,但我该如何访问它呢?

  3. 更新

    我找到了我遇到的第二个问题,因为我在这里找到了答案:

    UIStoryboard: What's the Correct Way to Get the Active Storyboard?

    UIStoryboard

    以上将创建一个新的故事板实例;为了获得活动实例,它更加简单:

    NSBundle *bundle = [NSBundle mainBundle];
    NSString *sbFile = [bundle objectForInfoDictionaryKey:@"UIMainStoryboardFile"];
    UIStoryboard *sb = [UIStoryboard storyboardWithName:sbFile bundle:bundle];
    

    在故事板文件中,您必须为要加载的视图设置标识符,例如UIStoryboard *sb = [[self.window rootViewController] storyboard]; 。之后,您实例化视图:

    LoginDialog

    在另一个视图控制器中,以下内容足够:

    LoginViewController *login = [sb instantiateViewControllerWithIdentifier:@"LoginDialog"];
    [self.window setRootViewController:login];
    

4 个答案:

答案 0 :(得分:13)

您只需重置窗口的根视图控制器

即可
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
      (NSDictionary *)launchOptions
{
   if(your_condition) {
       UIViewController *newRoot = [your implementation];
       self.window.rootViewController = newRoot;
   }
   return YES;
}

这对我有用,Xcode5.0.1

答案 1 :(得分:7)

我和你的情况类似。我的应用程序使用UINavigationController作为根视图控制器。如果用户已登录,我想向他/她显示NotLoggedInViewController,如果已登录,我想显示LoggedInViewController

在故事板中,UINavigationController只能有一个子节点,因此您必须能够以编程方式为其分配另一个根视图控制器。

我首先创建一个自定义导航控制器类,我们将其命名为MyNavigationController。在故事板中,我将此自定义类分配给导航控制器对象。

仍在故事板中,然后我为两个视图控制器建模,并将其中一个连接到导航控制器对象。由于我以后需要能够从我的代码中访问它们,因此我使用右侧的XCode检查器为每个代码分配一个标识符。这些标识符可以是任意字符串,但对于简单的事情我只使用类名。

最后,我在viewDidLoad类上实现MyNavigationController方法:

BOOL isLoggedIn = ...;

- (void)viewDidLoad {
  id rootController;
  if (isLoggedIn) {
    rootController = [self.storyboard instantiateViewControllerWithIdentifier:@"LoggedInViewController"];
  } else {
    rootController = [self.storyboard instantiateViewControllerWithIdentifier:@"NotLoggedInViewController"];
  }
  self.viewControllers = [NSArray arrayWithObjects:rootController, nil];
}

答案 2 :(得分:2)

我几乎没有使用故事板&可能这不是你问题的确切答案。但是我会建议你在不使用故事板的情况下在我的项目中做的事情。

didFinishLaunchingWithOptions AuthenticationViewController 中是第一个加载的视图。它要求登录凭据。输入后,它将输入项目使用的实际ViewControllers(即TabBar& all ..)。

添加到项目中的有趣功能是,当您输入凭据时,我弹出一个UIAleretView,要求用户选择三个选项中的一个。

  1. 不使用密码保存凭据
  2. 使用密码保存凭据
  3. 不要保存凭据
  4. 此处传递代码只是用户输入的4位数字。每当他想要“使用密码保存凭据”时,我pushViewController会显示默认键盘的默认键盘&完成输入后popviewController {}如果用户“不保存凭据”&稍后在播放应用程序时想要使用其他身份验证选项然后我将TabBarController的最后一个选项卡添加为“设置”选项卡,其中我允许用户选择其中一个身份验证选项,在开头的UIAlertView处弹出应用程序在登录后启动。

    别忘了在keychain

    中保存凭据

    简而言之,

    1. AuthenticationViewController->检查登录凭据是否存储在钥匙串中
    2. 1.1。如果没有存储(即3.不保存凭证) - >然后显示登录页面。

      1.2。如果凭证保存在钥匙串中 - >提取他们&看它是否与密码相关联。

      1.2.1。如果它与密码绑定(即2.使用密码保存凭证) ) - >然后显示密码页面。

      1.2.2。如果没有绑定(1.保存没有密码的凭据) - >然后显示/加载项目的TabBarController层次结构或其他内容。实际上你的应用程序开始了。

答案 3 :(得分:-1)

主要故事板已经加载,只需找到它的引用,以便我可以实例化另一个根视图控制器:

UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;

self.window.rootViewController = [mainStoryboard 
    instantiateViewControllerWithIdentifier:@"view-controller-id"];