我刚刚开始使用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;
}
但这提出了两个问题:
在此特定委托方法中,已根据故事板选择(并加载?)根视图控制器。我可以移动到加载过程中的早期位置来覆盖第一个视图控制器选择,还是会使问题不必要地复杂化?
要覆盖第一个视图控制器,我需要对故事板的引用,但我找不到比使用storyboardWithName:bundle:
的{{1}}构造函数更好的方法。这感觉不对,应用程序应该已经引用了故事板,但我该如何访问它呢?
更新
我找到了我遇到的第二个问题,因为我在这里找到了答案:
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];
答案 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
,要求用户选择三个选项中的一个。
此处传递代码只是用户输入的4位数字。每当他想要“使用密码保存凭据”时,我pushViewController
会显示默认键盘的默认键盘&完成输入后popviewController
{}如果用户“不保存凭据”&稍后在播放应用程序时想要使用其他身份验证选项然后我将TabBarController的最后一个选项卡添加为“设置”选项卡,其中我允许用户选择其中一个身份验证选项,在开头的UIAlertView
处弹出应用程序在登录后启动。
别忘了在keychain
中保存凭据简而言之,
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"];