Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy
Where are you calling this method from? I had an issue where I was attempting to present a modal view controller within the viewDidLoad
method. The solution for me was to move this call to the viewDidAppear:
method.
My presumption is that the view controller's view is not in the window's view hierarchy at the point that it has been loaded (when the viewDidLoad
message is sent), but it is in the window hierarchy after it has been presented (when the viewDidAppear:
message is sent).
Caution
If you do make a call to presentViewController:animated:completion:
in the viewDidAppear:
you may run into an issue whereby the modal view controller is always being presented whenever the view controller's view appears (which makes sense!) and so the modal view controller being presented will never go away...
Maybe this isn't the best place to present the modal view controller, or perhaps some additional state needs to be kept which allows the presenting view controller to decide whether or not it should present the modal view controller immediately.
Swift 4 Attempt to present ViewController whose view is not in the window hierarchy
This issue happens due to your view hierarchy.
You need to find out what is your Current/Topmost view controller in
view hierarchy and present your alert over it.
To find out topmost view controller use following code:
func getTopMostViewController() -> UIViewController? {
var topMostViewController = UIApplication.shared.keyWindow?.rootViewController
while let presentedViewController = topMostViewController?.presentedViewController {
topMostViewController = presentedViewController
}
return topMostViewController
}
And present your alert over topmost view controller and use main thread to present an alert because closures may have working on another thread.
DispatchQueue.main.async {
getTopMostViewController()?.present(alertController, animated: true, completion: nil)
}
Please refer to this stack answer:
Swift 3 Attempt to present whose view is not in the window hierarchy
Attempt to present ViewController whose view is not in the windows hierarchy
Issue
Current viewController is not the rootViewController
from UIApplication
. So you should find the current viewController which is visible and then present it from there.
Solution
Simply find the topViewController on your UIApplication Stack
, and from there present your controller.
let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2")
UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil)
This extension of UIApplication
comes in handy for your case
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
References: Gist
Attempt to present vc whose view is not in the window hierarchy
Add extention given bellow to your application and use it any where you want to present any view controller, it works for me hope it helps you.
//MARK: - UIApplication Extension
extension UIApplication {
class func topViewController(viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = viewController as? UINavigationController {
return topViewController(viewController: nav.visibleViewController)
}
if let tab = viewController as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(viewController: selected)
}
}
if let presented = viewController?.presentedViewController {
return topViewController(viewController: presented)
}
return viewController
}
}
And Present it by following code:
UIApplication.topViewController()?.present(vc, animated: true, completion: nil)
presenting whose view is not in the window hierarchy warning
Your LoginVC
is perfectly fine.
However, you need to change your HomeVC
as @Sh_Khan suggested and move the testing code from viewDidLoad
to viewDidAppear
:
import UIKit
import Firebase
class HomeVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// HomeVC.view was added to a view hierarchy
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// to check whether the user has already logged in or not
Auth.auth().addStateDidChangeListener { (auth, user) in
if user == nil {
let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)
}
}
}
}
Explanation
Your viewDidLoad
method gets called before the viewController
gets presented, so it at that moment it cannot really present another view controller (since it itself is not presented), viewDidLoad
documentation:
Called after the controller's view is loaded into memory.
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView() method. You usually override this method to perform additional initialization on views that were loaded from nib files.
In that moment the viewController is not in the window hierarchy yet.
viewDidAppear
however gets called when the view
is presented and becomes a part of the window hierarchy, viewDidAppear
documentation:
Notifies the view controller that its view was added to a view hierarchy.
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
Don't forget to call super.viewDidAppear
during overriding it.
I got this warning attempt to present ViewController whose view is not in the window hierarchy when I try to present a view
If you want to show VC1 from VC3 the you not need to present it again because it is already loaded in navigation stack. you just need to dismiss or pop
VC3 and VC2 from navigation stack. If you have presented it then dismiss and if you have pushed it then popped it.
Your warning's meaning : you are trying to presenting which is in the view hierarchy of navigation controller 1 but not in the view hierarchy of navigation controller 2.!!
Hope this will help :)
Swift 3 Attempt to present whose view is not in the window hierarchy
I have resolved the issue the main problem is exactly what it says the view is not in the view hierarchy. In order to resolve this issue we need to set the root view controller to the current view controller using the appDelegate object. So that the view now comes in the view hierarchy and be able to present further views. Here is the code
let initialViewController = UIStoryboard(name: "Main", bundle:nil).instantiateInitialViewController() as UIViewController
let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
appDelegate.window?.rootViewController = initialViewController
Please read this for further information. https://stackoverflow.com/a/27608804/5123516
Related Topics
How to Create Custom Calendar in React Native
Test iOS App on Device Without Apple Developer Program or Jailbreak
How to Return Value from Alamofire
Can't Use Swift Classes Inside Objective-C
Can You Attach a Uigesturerecognizer to Multiple Views
Any Way to Pre Populate Core Data
Adding Space/Padding to a Uilabel
Xcode Error "Could Not Find Developer Disk Image"
Best Way to Check If Object Is Out of Bounds in Array
How to Debug 'Unrecognized Selector Sent to Instance' Error
How to Rotate a Uiimage 90 Degrees
Firebase Query - Find Item With Child That Contains String
Error: 'Flutter/Flutter.H' File Not Found When Flutter Run on Ios