从AppDelegate

时间:2015-08-20 23:43:29

标签: ios objective-c uiviewcontroller storyboard

我需要从我的应用程序中呈现一个特定的ViewController(在swift中定义),它只是不起作用。这就是我在做的事情:

我在故事板Main.storyboard文件中定义了登录屏幕。该故事板有一个UINavigationController,它可以分割成一个故事板ID为“LoginVC”的屏幕。

当我第一次运行应用程序时,一切都很顺利。但是当用户为应用程序提供背景(按下主页按钮)时,我会自动注销用户,这意味着userDefaults中的变量“loggedin”设置为false。

当用户按下应用程序图标以启动/前景应用程序时,它会返回到它背景时所处的屏幕,这对应用程序来说非常标准,但不是我想要的。

在AppDelegate applicationDidBecomeActive中,我想检查用户默认值并查看我们是否已登录,如果没有,那么我想显示登录屏幕“LoginVC”。

我的代码如下所示。代码不会抛出任何错误,但它永远不会进入登录屏幕 - 它只是停留在同一个旧屏幕上。我做错了什么?

另请注意,MyLoginVC是在swift中定义的,所以我在AppDelegate中导入-Swift.h。

同样,所有内容都会编译,它看起来应该运行,它认为它已经注销并尝试显示登录屏幕,但它只是.doesn't.work。有什么想法吗?

- (void)applicationDidBecomeActive:(UIApplication *)application
{

    NSLog(@"applicationDidBecomeActive");

    BOOL loggedIn=[self.engine is_logged_in];
    if (loggedIn) {
        NSLog(@"self.engine says we are logged in");
    } else {
        NSLog(@"self.engine says we are NOT logged in");
        [self showLoginUI];
        NSLog(@"Are we at login screen yet?");
    }
}

- (void) showLoginUI {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    MyLoginVC *loginVC = [storyboard instantiateViewControllerWithIdentifier:@"LoginVC"];
    if (loginVC) {
        NSLog(@"loginVC is something");
    } else {
        NSLog(@"loginVC is nil");
    }
    //
    // Neither of these works!
    //
    //[self.window.rootViewController.navigationController presentViewController:loginVC animated:YES completion:nil];
    //[self.window.rootViewController.navigationController pushViewController:loginVC animated:YES];
}

更新:我无法相信我是第一个在应用程序重新进入前台并检测到用户现已注销时需要显示登录VC的人。也许我可以提供更多细节。我的故事板是Main.storyboard,最左边(初始)VC是一个普通的旧UINavigationController。这自动是rootViewController吗?与AppDelegate中的self.window.rootViewController相同的rootViewController是什么?是否有任何方法让应用程序检测到应用程序刚刚重新进入前台,现在必须显示登录VC,因为用户在应用程序进入后台时已注销。有人必须先解决这个问题。

3 个答案:

答案 0 :(得分:3)

通过反复试验,耐心和大量搜索,我偶然发现了正确的答案,或者至少是一种有效的方式。这是:

我的故事板在顶部有一个UINavigationController,然后连接到LoginVC(我不是一个故事板人,我没有编写接口代码,所以我怀疑“连接”是错误的单词但是你明白了。 UINavigationController有一个@“LoginScreen”的检查器IF,而Login VC的ID为@“LoginVC”。 LoginVC类已正确处理应用程序启动的情况,并正确检查用户是否已登录,如果用户已登录则转换到主应用程序屏幕。我需要处理的情况是用户最小化应用程序(通过按主页按钮)和我已经重载AppDelegate applicationDidEnterBackground以将用户注销。

当用户恢复应用程序时(通过按下图标),应用程序将进入前台并再次激活。在applicationDidBecomeActive中,我检查userDefaults以查看用户是否仍然登录。如果用户仍然登录,我不做任何其他事情。如果用户未登录,我会调用自己的AppDelegate函数showLoginUI来告诉应用程序切换到登录界面。这是函数:

-(void) showLoginUI {
    self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"LoginScreen"];
}

该函数中的这一行代码是我唯一需要做的事情,它就像一个魅力。看起来它将窗口rootViewController设置为新实例化的UINavigationController,它是故事板中的根VC。不确定引擎盖下发生了什么魔法,但它对我有用。

答案 1 :(得分:1)

对我来说,将此viewController推送到堆栈顶部似乎是错误的。我会尝试从堆栈中弹出其他viewControllers,直到我回到loginVC。 UINavigationController为此提供了一种非常方便的方法:

[self.window.rootViewController.navigationController popToViewController:savedLoginVC animated:NO];

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/popToViewController:animated

答案 2 :(得分:0)

当您的应用程序从后台返回到前台时。然后,您要执行的任何操作都在

中编写该代码

AppDelegate - > applicationWillEnterForeground方法

- (void)applicationWillEnterForeground:(UIApplication *)application 

{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}