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
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 :)
Warning: Attempt to present * on * whose view is not in the window hierarchy - swift
At this point in your code the view controller's view has only been created but not added to any view hierarchy. If you want to present from that view controller as soon as possible you should do it in viewDidAppear
to be safest.
Attempt to present OutgoingController: 0x1040e9600 on OutgoingController: 0x104042600 whose view is not in the window hierarchy
I fixed it by trying to fetch the top most view controller after interval of 0.5 seconds.
ie Im calling my displayOutgoingScreen function after interval of 0.5 seconds.
During that time my old Outgoing controller happens to be dismissed completely and I'm able to see my outgoing screen.
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)
Related Topics
Xcode 8 Recommend Me to Change the Min iOS Deployment Target from 7.1 to 8.0
Uiscrollview in Storyboard Not Working with iOS 8 Size Classes and Autolayout
Module Was Not Compiled for Testing' When Using @Testable
Watchkit Appicon - the App Icon Set Named "Appicon" Did Not Have Any Applicable Content
How to Lock Portrait Orientation for Only Main View Using Swift
How to Write Init Methods of a Uiviewcontroller in Swift
Improper Advertising Identifier [Idfa] Usage
Allow Unverified Ssl Certificates in Wkwebview
Cocoapods: Unable to Find a Specification for [Privatespec] Depended Upon by [Privateclientspec]
How to Stop/Cancel/Suspend/Resume Tasks on Gcd Queue
How to Use Autocorrection and Shortcut List in iOS8 Custom Keyboard
iOS Avplayer Trigger Streaming Is Out of Buffer
What Happens with Constraints When a View Is Removed
Swift - Segmented Control - Switch Multiple Views
iOS 7.1 Uitableviewcell Content Overlaps with Ones Below
Linker Errors When Trying to Install New Google Analytics 3.0 Beta