I've got a kind of complicated modal segue setup in my project. I'm trying to dismiss a view controller another view controller previously presented. I'm doing so with this code:
if(self.presentedViewController != nil){
print(self.presentedViewController!)
self.presentedViewController!.dismiss(animated: false)
print(self.presentedViewController!)
}
The prints are there for debugging purposes. They show that the presentedViewController doesn't actually get closed.
Even though I've set animated to false, I still see an animation occuring in the app when dismiss is called. Yet, the VC doesn't actually get dismissed.
Anyone knows a solution?
Apple
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, UIKit asks the presenting view controller to handle
the dismissal.
dismiss(animated:completion:) dismisses the view controller that was
presented modally by the view controller.
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss
If you present a view controller from the app's root, for example:
Presenting view controller
let root = UIApplication.shared.keyWindow!.rootViewController!
root.present(someViewController, animated: true, completion: nil)
You would dismiss it from the presented view controller like so:
Presented view controller
let root = UIApplication.shared.keyWindow?.rootViewController
root?.dismiss(animated: true, completion: nil)
Related
I'm using this library to show a side menu inside my app: https://github.com/jonkykong/SideMenu
All is fine except for one thing. When I present a viewcontroller from the side menu, and then dismiss this view controller to the main view controller, the viewWillAppear and/or viewDidAppear of the main view controller is not called ever.
From SideMenuVC (side menu view controller) I present other view controller:
let myPortfoliosNC = storyboard!.instantiateViewController(withIdentifier: "myPortfoliosNC")
present(myPortfoliosNC, animated: true, completion: nil)
Next, form the myPortfolioNC i dismiss (from the first view controller) and when go to main view controller the viewDidAppear and viewWillAppear is not called. Any idea of what i'm doing wrong ??
I have a container view that is set as the input accessory view for my view controller. Whenever I present a modal view controller the input accessory view dismisses.
I tried using the code below which works when I present the modal view controller. However, that view controller presents an image picker controller and after presenting that image picker controller I get the error "Keyboard cannot present view controllers." Is there a way to keep the input accessory view open for any view controllers presented on top of the base view controller.
let rootViewController: UIViewController = (UIApplication.shared.windows.last?.rootViewController)!
rootViewController.present(addVideoController, animated: true, completion: nil)
I don't think there is a way to keep an inputAccessoryView active through the view hierarchy - either pushing the view onto a navigationController stack or displaying modally will not keep the root's inputAccessoryView visible from my experience. This is because inputAccessoryView is a member of the UIViewController class rather than the window itself - and the new UIViewController you are making active does not have an inputAccessoryView.
I believe you will need to add a inputAccessoryView into the UIViewController class that you are presenting modally. You can set it up the exact same way that you did with the root view controller's class.
// call this in your root view controller that has the inputAccessoryView currently displayed
let addViewController = YourViewControllerClass()
modalViewController.inputAccessoryView = self.inputAccessoryView
self.present(addViewController, animated: true, completion: nil))
How to present a modal controller from another modally presented controller in iOS?
first, present a controller named sourceSelectorController modally:
self.present(sourceSelectorController, animated: true, completion: nil)
now ,how to present a new controller from sourceSelectorController modally?
I have a view controller that presents another view controller like so
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
let qrScannerViewController = QRScannerViewController()
qrScannerViewController.presentedBy = self
self.present(qrScannerViewController, animated:true, completion: nil)
// Do any additional setup after loading the view.
}
qrScannerViewController (the presented view controller) then calls
self.dismiss(animated:true, completion: nil)
which to my understanding calls the presenting view controllers dismiss function anyway.
Problem is, once the presented view controller has been dismissed, the presenting view controller's viewDidLoad gets called again, meaning the view controller is presented again.
Any ideas how to get around this?
Even if I use delegation the presenting view controller's viewDidLoad gets called again
Thanks
The presenting view controller is defined in a UITabController:
let qrPlaceholderViewController = QRPlaceholderViewController()
let controllers = [restaurantNavController,favouritesViewController, qrPlaceholderViewController, profileViewController]
self.viewControllers = controllers
Ok so the problem here was ARC doing its job.
When the presenting view controller presented the other view controller, ARC was unloading the presenting controller. This meant that when the presented view controller was dismissed, the presenting one was reinstantiated, hence forcing the viewDidLoad method to get called again
Solution:
A few solutions are available:
First of all I just stored a flag in a helper that I could check in the viewDidLoad method to see if it had already been loaded before and if it had, dont present the view controller again
Alternatively, I changed to once a qr code had been scanned, call a function in the presented view controllers delegate (the presenting controller) that navigated to the view that I wanted, therefore skipping the issue of the viewDidLoad being executed again.
let dialog: FriendCheckInDialogViewController = storyboard?.instantiateViewControllerWithIdentifier("FriendCheckInDialogViewController") as! FriendCheckInDialogViewController
dialog.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
If I use
self.navigationController?.presentViewController(dialog, animated: false, completion: nil)
Then transparency works. But popToRootViewControllerAnimated does not, so I cannot go back.
If I use
self.navigationController?.pushViewController(dialog, animated: false)
Then background becomes black instead of transparent. But popToRootViewControllerAnimated works, so I can go back.
What should I do?
You seem to be mixing different presentation styles.
If you present a view controller modally using presentViewController, then you can dismiss it using dismissViewController. In this case you can present the view controller modally over the current view controller.
If you push a view controller onto the navigation controller stack, then you can pop that view controller back off, but the pushed view controller replaces the current view controller, so you can't expose it "underneath".