How to move from one view controller to another using code on a specific condition in Swift?
if condition == true {
//use either VC Name associate or the Storyboard restoration id
//replace this with yours
if let Level2 = self.storyboard!.instantiateViewControllerWithIdentifier("MainVC") as? UIViewController
{
self.presentViewController(Level2, animated: true, completion: nil)
}
}
I think the problem is with you trying to cast the another VC to ViewController which i presume is the one that you are trying to segue from.
Make sure to have the storyboard ID and you can either type case to UIViewController to be broad or your specific VC to be specific.
Hope it helps.
Present a new view in SwiftUI
To show a modal (iOS 13 style)
You just need a simple sheet
with the ability to dismiss itself:
struct ModalView: View {
@Binding var presentedAsModal: Bool
var body: some View {
Button("dismiss") { self.presentedAsModal = false }
}
}
And present it like:
struct ContentView: View {
@State var presentingModal = false
var body: some View {
Button("Present") { self.presentingModal = true }
.sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
}
}
Note that I passed the presentingModal
to the modal so you can dismiss it from the modal itself, but you can get rid of it.
To make it REALLY present fullscreen
(Not just visually)
You need to access to the ViewController
. So you need some helper containers and environment stuff:
struct ViewControllerHolder {
weak var value: UIViewController?
}
struct ViewControllerKey: EnvironmentKey {
static var defaultValue: ViewControllerHolder {
return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)
}
}
extension EnvironmentValues {
var viewController: UIViewController? {
get { return self[ViewControllerKey.self].value }
set { self[ViewControllerKey.self].value = newValue }
}
}
Then you should use implement this extension:
extension UIViewController {
func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
toPresent.modalPresentationStyle = style
toPresent.rootView = AnyView(
builder()
.environment(\.viewController, toPresent)
)
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "dismissModal"), object: nil, queue: nil) { [weak toPresent] _ in
toPresent?.dismiss(animated: true, completion: nil)
}
self.present(toPresent, animated: true, completion: nil)
}
}
Finally
you can make it fullscreen
like:
struct ContentView: View {
@Environment(\.viewController) private var viewControllerHolder: UIViewController?
var body: some View {
Button("Login") {
self.viewControllerHolder?.present(style: .fullScreen) {
Text("Main") // Or any other view you like
// uncomment and add the below button for dismissing the modal
// Button("Cancel") {
// NotificationCenter.default.post(name: Notification.Name(rawValue: "dismissModal"), object: nil)
// }
}
}
}
}
Attempt to present UIAlertController whose view is not in the window hierarchy (Swift 3/Xcode 8)
First create UIAlertController such an attribute.
var alertController: UIAlertController?
And you must add this in the viewDidLoad() like this:
override func viewDidLoad() {
super.viewDidLoad()
self.alertController = UIAlertController(title: "Alert", message: "Not images yet", preferredStyle: .alert)
self.alertController?.addAction(UIAlertAction(title: "Close", style: .default))
view.addSubview((alertController?.view)!)
}
So when you press signInButton and login is incorrect you must invoke.
@IBAction func signInPressed(_ sender: Any) {
if usernameTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error in form", message: "Please enter an email and password.")
} else {
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: { (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil {
self.presentedViewController?.present(self.alertController!, animated: true, completion: nil)
}
}
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.
Warning: Attempt to present UIAlertController: whose view is not in the window hierarchy
Use this to present Alert.
func showResponseAlert(title:String?,message:String?){
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
topController.present(alert, animated: true, completion: nil)
}
}
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.
Swift: Attempt to present UIAlertController whose view is not in the window hierarchy!
This line:
ViewController().present(alertView!, animated: true, completion: nil)
creates a new instance of ViewController
and calls the present
method on it. That won't work. You need to call it from a view controller that is itself presented. It looks like that code is inside ConsoleViewController
, maybe you can just use self
there.
SwiftUI [Presentation] Attempt to present ... on ... whose view is not in the window hierarchy
I suppose it's because by confirming the cancel you dismiss both the .confirmationDialog
and the parent .sheet
. I believe it doesn't hurt, but you can get rid of it like this:
Button("Discard Changes", role: .destructive) {
DispatchQueue.main.async {
isPresentingEditView = false
}
}
..and put it here:
.sheet(isPresented: $isPresentingEditView) {
NavigationView {
Text("DetailEditView(data: $data)")
.navigationTitle(Text("(scrum.title)"))
.toolbar {
ToolbarItemGroup(placement: .cancellationAction) {
Button("Cancel") {
isShowingConfirmationDialog = true
}
}
ToolbarItemGroup(placement: .confirmationAction) {
Button("Done") {
isPresentingEditView = false
// scrum.update(from: data)
}
}
}
// vvv Here
.confirmationDialog(
"Are you sure you want to discard your changes?",
isPresented: $isShowingConfirmationDialog
) {
Button("Discard Changes", role: .destructive) {
DispatchQueue.main.async {
isPresentingEditView = false
}
}
Button("Keep Editing", role: .cancel) {
isShowingConfirmationDialog = false
}
} message: {
Text("Are you sure you want to discard your changes?")
}
}
}
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 :)
Related Topics
Swift - Image Data from Ciimage Qr Code/How to Render Cifilter Output
While Scrolling on an iOS Device, the Z-Index of Elements Isn't Working
How to Know That If the Only Visible Area of a .Png Is Touched in Xcode
How to Disable the Network in iOS Simulator
How to Add a Container View Programmatically
Xcode Changes Unmodified Storyboard and Xib Files
How to Save Nsmutablearray in Nsuserdefaults
iOS 6 - Viewdidunload Migrate to Didreceivememorywarning
Using Existing System Sounds in iOS App [Swift|
Missing Push Notification Entitlement Warning
Uidevice Currentdevice Model Possible Values
-[Nsnull Length]: Unrecognized Selector Sent to JSON Objects
Running Individual Xctest (Ui, Unit) Test Cases for iOS Apps from the Command Line
How to Programmatically Increase Uitableview Cell's Height in Iphone
How to Fix Failed to Fetch Default Token Error
Why Is Our Monotouch App Breaking in the Garbage Collector? It Is Not Out of Memory