ios - 更改了 rootViewController 但旧 rootViewController 的 View 仍在 View 层次结构中

标签 ios swift uiwindow

我有一个基本情况,当用户通过身份验证后,我删除当前屏幕(登录屏幕)并将其更改为应用程序内的另一个屏幕。

为此,我使用以下代码:

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
    print("Window's subviews before removed = \(appDelegate.window?.subviews)")

    appDelegate.window?.subviews.forEach { $0.removeFromSuperview() }

    print("Window's subviews after removed = \(appDelegate.window?.subviews)")

    appDelegate.window?.rootViewController?.view?.removeFromSuperview()
    appDelegate.window?.rootViewController?.removeFromParentViewController()

    appDelegate.window?.rootViewController = newRootViewController

    print("Window's subviews after changed = \(appDelegate.window?.subviews)")
}

这是输出:

enter image description here

这是用户可以在设备屏幕上看到的内容 - 看起来还不错: enter image description here

但是,在 Debug View Hierarchy 工具中却不行:

enter image description here

如您所见,旧 rootViewController 的 View 仍然存在于 UIWindow 中,但不是它的 subview - 正如输出所示。

这个行为看起来很奇怪,有没有人遇到过这个问题?

最佳答案

原因:

我在使用 Google 登录 SDK 和 Facebook 登录 SDK 登录时尝试替换 rootViewController 时遇到了这个问题。

这些 SDK 有一个像这样的身份验证屏幕:

enter image description here

通过使用 Debug View Hierarchy,我意识到当显示身份验证屏幕 (2) 时,应用将 rootViewController 更改为 UITransitionView。当身份验证屏幕消失 (3) 时,它再次将 rootViewController 更改为显示身份验证屏幕 (1) 之前的状态。

状态(1):在呈现身份验证屏幕之前,rootViewControllerLoginViewController

状态(2):呈现认证画面,rootViewController变为UITransitionView

状态(3):关闭身份验证屏幕后,rootViewController 已返回到 LoginViewController

调试 View 层次结构中的状态 (1) + (3): enter image description here

调试 View 层次结构中的状态 (2): enter image description here

我将更改rootViewController的代码放在相应SDK的每个委托(delegate)方法中,当身份验证完成时调用。

Google 登录 SDK:signIn:didSignInForUser:withError:

Facebook 登录 SDK:logInWithReadPermissions:fromViewController:handler:

这些方法在用户通过身份验证后立即调用,而不管身份验证屏幕是否被关闭。

这意味着,有时,当用户的身份验证过程完成得太快时,甚至在身份验证屏幕关闭并且 rootViewController 更改为 LoginViewController 之前,就会出现问题。这意味着,当用户已通过身份验证但 rootViewController 仍然是 UITransitionView 时,问题出现在两种状态 (2) 和 (3) 之间。

解决方案:

暂时,在我找到更好的解决方案之前,我防止用户的身份验证过程发生得太快,这意味着我等待状态 (3) 在 delaying 之前完成用户通过身份验证并更改 rootViewController 后 0.25 秒。

0.25 的时间足以让一切正常工作,但太快了用户会失去耐心。

关于ios - 更改了 rootViewController 但旧 rootViewController 的 View 仍在 View 层次结构中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50289680/

相关文章:

ios - 使用 RestKit 序列化 JSON 时忽略 nil 属性

ios - 如何永久修复 Xcode 5 SpringBoard 无法启动应用程序,错误为 : -3

iphone - 如何将 UIView 始终放在顶部屏幕上?

iphone - 检测全局 UIWindow 对象上的触摸事件

iphone - UIWindow rootViewController 的向后兼容性

ios - 长按时像 iMessage 一样突出显示 UITableViewCell

ios - 如何使用带有 Storyboard 的 Autolayout 获取 UIView 子类的框架?

ios - 如何在 Swift 中将具有十六进制数据的 NSData 对象转换为 ASCII?

ios - 如何在 firebase 的节点中添加子节点

swift - VideoComposition 不遵守指示