Swift : present a ViewController while alert is shown - ios

I have a problem with present UIViewController Modaly by above code
self.presentViewController(view, animated: true, completion: nil);
it doesn't work when another view present modaly such as UIAlert,its triggered by a socket packet in background and user may is performing another work and may another modal view already presented when the trigger happens.

You can not present two view controllers at the same time from the same source controller. Instead, try presenting the second view controller from the first one that was presented.
if let presented = self.presentedViewController {
presented.present(vcToPresent, animated: true, completion: nil)
}
else {
self.present(vcToPresent, animated: true, completion: nil)
}

Related

How to dismiss a viewController to rootViewController without showing any VCs in between dismiss process?

Let say I have the following VCs:
RootVC --> VC A --> VC B
I'm using present method to present view controller from RootVC to VC A then to VC B. Now I'm on VC B and I want to dismiss from VC B back to RootVC using
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
it works but I still see VC A shows up during the dismiss process. Then, I try this method
self.presentationController?.presentedViewController.dismiss(animated: true, completion: nil)
It also works to dismiss back to root VC but I still see VC A in process.
My question is is there a way to not show VC A during the dismiss process? I already try animated: false but still get the same result. Thanks!
You need to make the change in the modalPresentationStyle to the .custom. The custom will allow you to view the presentingViewController view when the current visible controller's view is transparent.
Now when you want to go back to root view on the current presenting stack you need to call the method dismissToRootViewController(animated: completion:).
In the implementation of this method will allow all intermediate presenting view controller view to be transparent which will give you dismiss animation from VC c to RootVC.
extension UIViewController {
func dismissToRootViewController(animated: Bool, completion: (() -> Swift.Void)? = nil) {
var viewController = self.presentingViewController
while viewController?.presentingViewController != nil {
viewController?.view.alpha = 0.0
viewController = viewController?.presentingViewController
}
self.dismiss(animated: true) {
viewController?.dismiss(animated: false, completion: completion)
}
}
}
You can try to use this:
navigationController?.popToRootViewController(animated: false)

Dismissing presented view controller returns to root view of navigation controller

I have a UINavigationController that has a stack of view controllers. Something like below:
[RestListViewController, RestViewController, ProdListViewController]
ProdListViewController presents another view controller ProdViewController.
When I call
self.dismiss(animated: true, completion: nil)
I am returned the the RestListViewController
I understand this is because the UINavigationController is released when the view controller is presented, therefore is reloaded.
Is there any way I can stop this happening and have the dismiss function return to the original vc stack?
Edit:
ProdViewController is presented as so
let productViewController = ProdViewController()
self.present(productViewController, animated: true, completion: nil)
and dismissed
self.dismiss(animated: true, completion: nil)

How to correctly close modal presented controller

I am opening a navigationController using either directly navigation segue in storyboard or called segue from code, but still created on storyboard.
Example:
self.performSegue(withIdentifier: "addNew", sender: nil)
Which then with modal transition opens a navigationController. NC then has a few view controllers on which all have close button on them and when I click on it it closes NC using:
self.navigationController?.dismiss(animated: true, completion: nil)
But afterwards when I switch between different ViewControllers on TabbarController or open some other view with push view I get:
Unbalanced calls to begin/end appearance transitions for
And also viewWillAppear on opened view isn't called. So can anyone tell me if I'm closing the NC correctly or is there some other way to prevent the error.
EDIT1:
changed the closing call from
controller.navigationController?.dismiss(animated: true, completion: nil)
to self.navigationController?.dismiss(animated: true, completion: nil) just to make the question easier.
Also tired:
self.dismiss(animated: true, completion:nil)
EDIT2:
Is it maybe bad to open a NC from VC that is on NC that is on UITabbarController or is just simply already bad to have NavigationControllers as tabs on TabbarController?
You may need to close the controller from that controller's side:
// place this to the target controller, which handles you that modal view
self.dismiss(animated: true) {
//completion:
}
or
self.dismiss(animated: true, completion:nil)

iOS - How to not present model view if it is presenting?

I have a floating button to present a model view. I call presentViewController in AppDelegate
UIApplication.sharedApplication().keyWindow?.rootViewController!.getTopViewController().presentViewController(myViewController, animated: false, completion: nil)
When myViewController is presenting, I click my floating button again and my application will call myViewController one more time. So how to not present if it presenting?
What you can do is add a check on your button to check whether the present controller is presenting something which can be done like this
let controller = UIApplication.sharedApplication().keyWindow?.rootViewController!.getTopViewController()
if controller.presentedViewController == nil {
controller.presentViewController(myViewController, animated: false, completion: nil)
}

View over view breaks hierarchical

I'm using MZFormSheetPresentationController to show as "pop-up" a ViewController2 (embedded in a Navigation controller as suggested) over a ViewController1.
My ViewController1 has a searchbar, a UISegmentedControl and a tableview:
When user clicks on the searchbar bookmark button, pop-up is shown.
I'd like to close the pop-up when user clicks on the done button and it works great using self.dismissViewControllerAnimated(true, completion: nil) method but I'm looking for more. I'd like to present again ViewController1 so tableView will reload data.
I tried with:
self.dismissViewControllerAnimated(true, completion: nil)
print("Dismissed")
//goToTickets
let next = self.storyboard?.instantiateViewControllerWithIdentifier("myTabBar") as! UITabBarController
self.presentViewController(next, animated: true, completion: nil)
but I get this error:
Warning: Attempt to present on whose view is not in the window hierarchy!
Pop-up disappears but I can't present ViewController.
How can I do?
Thanks in advance.
Edit
This is my ViewController2 with identifier "navigationFilter"
and my tabBar:
When you are in the middle of dismissing you are trying to present next ViewController, you have to wait for completion handler and then present next view controller like this:
self.dismissViewControllerAnimated(true, completion: {
let next = self.storyboard?.instantiateViewControllerWithIdentifier("myTabBar") as! UITabBarController
self.presentViewController(next, animated: true, completion: nil)
})

Resources