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

Posted

技术标签:

【中文标题】iOS:从任何地方返回根视图控制器【英文标题】:iOS: return to root view controller from anywhere 【发布时间】:2014-09-15 18:32:35 【问题描述】:

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

这是我的应用流程:

 +-------------------+
+----------------------------> |
| |根视图控制器 |
| +---------+UIViewController +------+
| | +-------------------+ |
| | |
| +-------v---------+ +----+----v-----------------+
| |登录故事板 | |SWRevealViewController |
| |2 次观看 | |见注释 |
| +-------+---------+ +---+-------+---+
| | | |
| | | |
+---------------+ +------------v--------+ +----v------- -------------------------------------+
                                     |抽屉 | |主故事板 |
                                     | UIViewController | |从 UINavigationController | 开始
                                     +------------------+ | |
                                                               +--------------------------------------------------+

SWRevealViewController 是一头奇怪的野兽...它同时显示两个 UIViewController,一个在另一个前面,后面的一个就像一个“抽屉”,这样前面的一个可以滑到一边访问它。

【问题讨论】:

也许使用观察者的 nsnotification 中心以模态方式呈现登录控制器? 向我们提供有关您的视图控制器层次结构的更多详细信息。 @Yanchi 我不太了解通知中心,但我不会有同样的问题来弄清楚 如何 从通知处理程序? @robmayoff 我添加了我的视图控制器和故事板流程的图表(使用我刚刚发现的漂亮工具 asciiflow.com 创建) 【参考方案1】:

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

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

[self dismissViewControllerAnimated:YES];

Dismiss,当在根 vc (self) 上调用时,不关心顶部的视图控制器是什么,或者中间有多少,它会删除所有内容以显示调用它的 vc。该根 vc 将有其 viewDidAppear** 火灾,您构建它是为了根据登录状态做正确的事情。

【讨论】:

这是一个有趣的可能性...目前在我的根视图控制器中,我通过addChildViewControlleraddSubview 显示登录或显示视图,因为当我使用presentViewController 尝试它时一个显着的延迟显示根视图控制器的空白屏幕(甚至从 viewDidLoad 调用)。你能想出这与你的建议有什么关系吗? 我的错。演示只能在 viewDidAppear 或之后发生。但是,如果您在 viewDidAppear 中显示动画=NO,您应该不会看到任何延迟。将编辑我的答案。【参考方案2】:

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

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

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

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

当你想注销时,只需调用,你应该会弹出到注销屏幕

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

根据您的图表,我不会考虑返回注销屏幕,而是弹出所有视图控制器,直到显示出来

【讨论】:

【参考方案3】:

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

我最初从我的根视图控制器的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];
                            ];

另一种方式的过渡效果类似。 switchToLoginScreen 方法是从我的应用程序委托中的处理程序调用的,它可以通过self.window.rootViewController 访问根视图控制器。应用程序委托在应用程序启动时将自己注册为 HTTP 401 处理程序的委托人。谢谢丹;虽然你的回答并没有直接解决我的问题,但它确实让我以一种新的方式思考这个问题,从而让我找到了答案!

【讨论】:

以上是关于iOS:从任何地方返回根视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用委托将数据从多个视图控制器传递回根视图控制器? IOS 7

返回根视图控制器

从任何其他选项卡的视图控制器中弹出第二个选项卡的根视图(默认)

在运行时更改 iOS 13 中的根视图控制器

带有自定义后退按钮的滑动手势冻结根视图控制器

Ios:当应用程序处于非活动状态时,如何让我的应用程序返回根视图