iOS:从任何地方返回到根视图控制器

时间:2014-09-15 18:32:35

标签: ios objective-c iphone

我正在编写一个需要登录服务器的iPhone应用程序。应用程序的根视图控制器检查用户是否已登录并有条件地将用户发送到两个故事板(登录或主应用程序)之一。根控制器不是UINavigationController(我见过这个问题的许多解决方案都假设它是)。如果用户在服务器上注销(超时等),服务器请求将返回HTTP 401,我在我的Web请求代码中拦截...如何让用户将其退回到登录屏幕和/或根视图控制器?我已经搜索了StackOverflow和其他互联网几个小时,我找不到答案。我尝试过Unwind Segue,它似乎被正确调用(没有错误),但它实际上并没有放松到根视图控制器,也许是因为我直接在根视图控制器上调用它,这是我的网络请求类中只有一个可见。有什么想法吗?

这是我的应用流程:

                           +-------------------+                                                      
+-------------------------->                   |                                                      
|                          |RootViewController |                                                      
|               +----------+UIViewController   +------+                                               
|               |          +-------------------+      |                                               
|               |                                     |                                               
|       +-------v---------+                 +----+----v-----------------+                             
|       |Login storyboard |                 |SWRevealViewController     |                             
|       |2 Views          |                 |see note                   |                             
|       +-------+---------+                 +---+-------------------+---+                             
|               |                               |                   |                                 
|               |                               |                   |                                 
+---------------+                    +----------v-------+      +----v--------------------------------+
                                     | Drawer           |      |  Main Storyboard                    |
                                     | UIViewController |      |  Starts with UINavigationController |
                                     +------------------+      |                                     |
                                                               +-------------------------------------+

SWRevealViewController是一个奇怪的野兽......它同时显示两个UIViewControllers,一个在另一个前面,后面一个像“抽屉”,这样前面的一个可以滑动除了访问它。

3 个答案:

答案 0 :(得分:2)

在RootViewController viewDidLoad中,订阅注销通知。在viewDidAppear中的同一个类中,检查用户的登录状态。如果用户需要在LoginViewController上登录presentViewController,否则显示SWRevealController。

在通知处理程序中,如果用户丢失了登录状态,请执行以下操作:

[self dismissViewControllerAnimated:YES];

当在根vc(self)上调用时,忽略不关心什么视图控制器在顶部,或者它们之间有多少,它会删除所有内容以显示调用它的vc。根vc将根据登录状态生成viewDidAppear ** fire,以便做正确的事情。

答案 1 :(得分:0)

在登录视图控制器中,您可以使用本地通知中心添加监听器

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidLogout:) name:@"UserDidLogoutNotificationName" object:nil];

在您的通知引用的方法中,关闭视图控制器。

-(void)userDidLogout {
    [self dismissViewControllerAnimated:YES completion:nil];
 }

每当你想要注销时,你就应该弹出到你的注销屏幕

[[NSNotificationCenter defaultCenter]postNotification:@"UserDidLogoutNotificationName"]

根据你的图表,我不会考虑回到退出屏幕,而是弹出所有的视图控制器,直到它被揭示

答案 2 :(得分:0)

正如我comment danh's answer所指出的,我可能遗漏了一个重要的细节。我将登录屏幕和主屏幕呈现为根视图控制器的子视图控制器。在思考这一段时间后,我意识到解决方案是交换子视图控制器。随后进行了大量的研究和咬牙切齿,我找到了一种似乎可靠的解决方案。

我最初在我的根视图控制器viewDidLoad中显示一个屏幕(这里是主屏幕),如下所示:

[self addChildViewController:self.mainViewController];
[self.view addSubview:self.mainViewController.view];
[self.mainViewController didMoveToParentViewController:self];
[self.view layoutIfNeeded];

然后当我想切换到登录界面时,我这样做:

- (void)switchToLoginScreen
{
    [self switchScreensFrom:self.mainViewController to:self.loginViewController];
}

- (void)switchScreensFrom:(UIViewController *)fromViewController to:(UIViewController *)toViewController
{
    [fromViewController willMoveToParentViewController:nil];
    [self addChildViewController:toViewController];

    [self transitionFromViewController:fromViewController
                      toViewController:toViewController
                              duration:0.25
                               options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
                            animations:^{}
                            completion:^(BOOL finished){
                                [fromViewController removeFromParentViewController];
                                [toViewController didMoveToParentViewController:self];
                            }];
}

另一种方式的转变同样有效。从我的app委托中的处理程序调用{​​{1}}方法,该委托可以通过switchToLoginScreen访问根视图控制器。应用程序委托在app start时将自己标记为HTTP 401处理程序的委托。谢谢你;虽然你的答案没有直接解决我的问题,但它确实让我以一种新的方式思考问题,这使我得到答案!