从 AppDelegate 有条件地从情节提要中的不同位置开始
我设置了一个故事板,其中包含工作登录和主视图控制器,后者是登录成功时用户导航到的视图控制器。 我的目标是如果身份验证(存储在钥匙串中)成功,则立即显示主视图控制器,如果身份验证失败,则显示登录视图控制器。 基本上,我想在我的AppDelegate中执行此操作:
// url request & response work fine, assume success is a BOOL here
// that indicates whether login was successful or not
if (success) {
// 'push' main view controller
} else {
// 'push' login view controller
}
我知道方法performSegueWithIdentifier:但此方法是UIViewController的实例方法,因此无法从AppDelegate内调用。 如何使用现有的故事板来做到这一点?
编辑:
故事板的初始视图控制器现在是一个未连接到任何东西的导航控制器。我使用了 setRootViewController: 区别,因为 MainIdentifier 是一个 UITabBarController。这就是我的台词:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL isLoggedIn = ...; // got from server response
NSString *segueId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:segueId];
if (isLoggedIn) {
[self.window setRootViewController:initViewController];
} else {
[(UINavigationController *)self.window.rootViewController pushViewController:initViewController animated:NO];
}
return YES;
}
欢迎提出建议/改进!
I have a storyboard set up with working login and main view controller, the latter is the view controller to which the user is navigated to when login is successful.
My objective is to show the main view controller immediately if the authentication (stored in keychain) is successful, and show the login view controller if the authentication failed.
Basically, I want to do this in my AppDelegate:
// url request & response work fine, assume success is a BOOL here
// that indicates whether login was successful or not
if (success) {
// 'push' main view controller
} else {
// 'push' login view controller
}
I know about the method performSegueWithIdentifier: but this method is an instance method of UIViewController, so not callable from within AppDelegate.
How do I do this using my existing storyboard ??
EDIT:
The Storyboard's initial view controller now is a navigation controller which isn't connected to anything. I used the setRootViewController: distinction because MainIdentifier is a UITabBarController. Then this is what my lines look like:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL isLoggedIn = ...; // got from server response
NSString *segueId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:segueId];
if (isLoggedIn) {
[self.window setRootViewController:initViewController];
} else {
[(UINavigationController *)self.window.rootViewController pushViewController:initViewController animated:NO];
}
return YES;
}
Suggestions/improvements are welcome!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我对这里建议的一些解决方案感到惊讶。
实际上不需要在故事板中使用虚拟导航控制器来隐藏视图和视图。在 viewDidAppear: 上触发 segues: 或任何其他 hack。
如果您没有在 plist 文件中配置故事板,您必须自己创建窗口和根视图控制器:
如果情节提要在应用程序的plist中配置,在调用 application:didFinishLaunching: 时,窗口和根视图控制器已经设置完毕,并且将在窗口上调用 makeKeyAndVisible。
在这种情况下,就更简单了:
I'm surprised at some of the solutions being suggested here.
There's really no need for dummy navigation controllers in your storyboard, hiding views & firing segues on viewDidAppear: or any other hacks.
If you don't have the storyboard configured in your plist file, you must create both the window and the root view controller yourself :
If the storyboard is configured in the app's plist, the window and root view controller will already be setup by the time application:didFinishLaunching: is called, and makeKeyAndVisible will be called on the window for you.
In that case, it's even simpler:
我假设您的故事板被设置为“主故事板”(Info.plist 中的键
UIMainStoryboardFile
)。在这种情况下,UIKit 将加载 Storyboard 并将其初始视图控制器设置为窗口的根视图控制器,然后再将application:didFinishLaunchingWithOptions:
发送到您的 AppDelegate。我还假设故事板中的初始视图控制器是导航控制器,您想要将主视图控制器或登录视图控制器推送到该导航控制器上。
您可以向窗口询问其根视图控制器,并向其发送
performSegueWithIdentifier:sender:
消息:I assume your storyboard is set as the "main storyboard" (key
UIMainStoryboardFile
in your Info.plist). In that case, UIKit will load the storyboard and set its initial view controller as your window's root view controller before it sendsapplication:didFinishLaunchingWithOptions:
to your AppDelegate.I also assume that the initial view controller in your storyboard is the navigation controller, onto which you want to push your main or login view controller.
You can ask your window for its root view controller, and send the
performSegueWithIdentifier:sender:
message to it:如果您的故事板的入口点不是
UINavigationController
:如果您的故事板的入口点是
UINavigationController
将: 替换为:
IF your storyboard's entry point isn't an
UINavigationController
:IF your storyboard's entry point IS an
UINavigationController
replace:with:
在 AppDelegate 的
application:didFinishLaunchingWithOptions
方法中,在return YES
行之前添加:将
YourStartingViewController
替换为实际的第一个视图控制器类的名称 (你不想出现的那个)和YourSegueIdentifier
以及该启动控制器和你想要实际启动的控制器之间的实际名称(在继续)。如果您并不总是希望发生这种情况,请将该代码包含在
if
条件中。In your AppDelegate's
application:didFinishLaunchingWithOptions
method, before thereturn YES
line, add:Replace
YourStartingViewController
with the name of your actual first view controller class (the one you don't want to necessarily appear) andYourSegueIdentifier
with the actual name of the segue between that starting controller and the one you want to actually start on (the one after the segue).Wrap that code in an
if
conditional if you don't always want it to happen.鉴于您已经在使用故事板,您可以使用它向用户展示 MyViewController,一个自定义控制器(归结为按照本的回答< /a> 一点)。
在AppDelegate.m中:
传递给instantiateViewControllerWithIdentifier的字符串指的是Storyboard ID,可以在界面构建器中设置:
只需根据需要将其包装在逻辑中即可。
但是,如果您从 UINavigationController 开始,则此方法不会为您提供导航控件。
要从通过界面生成器设置的导航控制器的起点“向前跳转”,请使用以下方法:
Given that you're already using a Storyboard, you can use this to present the user with MyViewController, a custom controller (Boiling down followben's answer a bit).
In AppDelegate.m:
The string passed to instantiateViewControllerWithIdentifier refers to the Storyboard ID, which can be set in interface builder:
Just wrap this in logic as needed.
If you're starting with a UINavigationController, though, this approach will not give you navigation controls.
To 'jump forward' from the starting point of a navigation controller set up through interface builder, use this approach:
为什么不先出现登录屏幕,检查用户是否已经登录并立即推送下一个屏幕?一切都在ViewDidLoad中。
Why not have the login screen which appears first, check if the user is already logged in and push the next screen straight away? All in the ViewDidLoad.
快速实现相同:
如果您使用
UINavigationController
作为故事板中的入口点Swift implementation of same :
If you use
UINavigationController
as entry point in storyboard这是在 iOS7 上有效的解决方案。
为了加快初始加载速度并且不进行任何不必要的加载,我在 Storyboard 文件中有一个名为“DUMMY”的完全空的 UIViewcontroller。然后我可以使用以下代码:
This is the solution that worked n iOS7.
To speed up the initial loading and not do any unnecessary loading, I have a completely empty UIViewcontroller called "DUMMY" in my Storyboard file. Then I can use the following code:
我建议创建一个新的 MainViewController,它是导航控制器的根视图控制器。为此,只需按住控件,然后拖动导航控制器和 MainViewController 之间的连接,从提示中选择“关系 - 根视图控制器”。
在 MainViewController 中:
记住在 MainViewController 与 Home 和 Login 视图控制器之间创建 Segues。
希望这有帮助。 :)
I suggest to create a new MainViewController that is Root View Controller of Navigation Controller. To do that, just hold control, then drag connection between Navigation Controller and MainViewController, choose 'Relationship - Root View Controller' from prompt.
In MainViewController:
Remember to create segues between MainViewController with Home and Login view controllers.
Hope this helps. :)
在尝试了许多不同的方法之后,我能够用以下方法解决这个问题:
After trying many different methods, I was able to solve this problem with this: