父视图控制器未解除

Posted

技术标签:

【中文标题】父视图控制器未解除【英文标题】:Parent view controller not dismissed 【发布时间】:2017-02-27 18:29:00 【问题描述】:

presentViewControllerfunction 有问题。

我有一个登录菜单 (A) 和一个显示登录表单的按钮 (B)。成功登录后,我会使用self.presentViewController (C) 呈现第三个视图。

登录菜单 (A) -> 登录表单 (B) -> 内容 (C)

它的工作,我可以呈现第三个视图 (C) 但登录菜单 (A) 始终可见(我可以在 UI 调试模式中看到它)。

那么,如何关闭A ViewController?

【问题讨论】:

登录后在 ->content (C) 中关闭当前视图控制器 你试过 self.navigationController 解散吗?? 这就是 presentViewController 的工作方式。如果您从 A 呈现 B,这并不意味着它会关闭 A。如果您想将“内容”设置为 rootController,那么您必须更改 window.rootviewcontroller = yourviewcontroller。 您可能需要将层次结构的顺序更改为最合乎逻辑的顺序,例如Content (A) ➜ Login Menu (B) ➜ Login Form (C),所以当您关闭登录表单和视图时,它回退到应有的内容 (A)。 ***.com/questions/19962276/… 参考最佳实践 【参考方案1】:

presentViewController,以模态方式呈现视图控制器。换句话说,在当前视图控制器的内容上,当前视图控制器不会被释放。

为您的示例使用以下代码:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: <Identifier as in Storyboard of C>)
(UIApplication.shared.delegate as! AppDelegate).window?.rootViewController = vc

如果您想包含一个过渡,您可以将最后一行替换为以下内容:

UIView.transition(from: currentRootViewController!.view, to: vc.view, duration: 0.8, options: .transitionCrossDissolve, completion:  (_) in
      (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController = vc
)

【讨论】:

@YoannLth :这是您可以更改根控制器的方式 OP 的帖子似乎是XY Problem,因此您需要为他解决问题 X,而不是为问题 Y 提供过于复杂的解决方案。 我试过这个答案@Wolverine,但它没有用。我用一个肮脏的hack解决了这个问题:我用self.view.window!.rootViewController?.dismissViewControllerA‌​nimated(false, completion: nil)关闭了所有视图控制器,它返回到应用程序入口点,这是一个检查用户是否登录的ViewController。 @YoannLth,我按照holex 的建议简化了解决方案。我认为我对你的解释的问题在于我指向了 initialVC,而你的 C 可能不是你的 initialVC。【参考方案2】:

我认为本教程有你的答案https://www.youtube.com/watch?v=WIaRs2d6Xm0

【讨论】:

【参考方案3】:

如果我们考虑 presentVieController 机制,这不是问题或错误。不过,如果您觉得您不希望之前的控制器保留在 Hierarchy 中,那么您必须更改流程。

目前您的流程是:

A -> RootViewController。 B -> 登录屏幕 C -> 容器

我建议参考以下答案以获得最佳实践。

Best practices for Storyboard login screen, handling clearing of data upon logout

如果您提出处理流程的想法,您可以解决您的问题。这是我的建议

建议

    您将C设置为rootController,在C的ViewDidLoad中,检查天气用户是否登录,如果用户未登录,则可以显示A ,然后您可以从那里呈现 B。成功登录后,您可以关闭 AB 并根据登录的用户值刷新您的 rootController C

要关闭多个视图控制器,您可以尝试以下代码

-(void)dismissModalStack 
    UIViewController *vc = self.presentingViewController;
    while (vc.presentingViewController) 
        vc = vc.presentingViewController;
    
    [vc dismissViewControllerAnimated:YES completion:NULL];

    也可以使用ContainerView机制,将C设置为rootController,在C中,取一个ContainerView 可以在其中显示AB,登录后可以删除它们并刷新C

希望对你有帮助!

【讨论】:

以上是关于父视图控制器未解除的主要内容,如果未能解决你的问题,请参考以下文章

在模态视图被解除后,父视图控制器中是不是有一个委托被调用?

不允许在解除分配时尝试加载视图控制器的视图,这可能会导致未定义的行为

BAD_EXC_ACCESS 用于在解除分配时尝试加载视图控制器

视图控制器解除动画参数

父视图中容器视图的自动布局未与布局指南对齐

模态视图控制器使背景变黑