I have a UITableViewControllerthat presents a UIViewController modally when didSelectRowAtis invoked.
My application is wrapped in a UITabBarController.
I would like to dismiss the UIViewController when a user changes tabs.
I have tried to call dismiss on my controller like so, but this does not work.
let vc = VimeoController()
....
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
vc.dismiss(animated: true) {
print("dismissed")
}
}
...
fileprivate func presentModal() -> Void {
vc.modalPresentationStyle = .overCurrentContext
present(vc, animated: true, completion: nil)
}
Place your dismiss call within the viewDidDisappear lifecycle hook of your VimeoController controller instead.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
dismiss(animated: true, completion: nil)
}
I'm trying to present a view controller once the QRCode reader has been dismissed, however when doing this the QRCode reader view controller is presented again. The code snippet below shows the method and how I'm dismissing the view and how I'm trying to present the next view controller. Any idea on why the QR reader view controller keeps presenting its self when I try to present a different controller.
func readerDidCancel(_ reader: QRCodeReaderViewController) {
dismiss(animated: true, completion: nil)
present(ClockInOrOutViewController(), animated: true, completion: nil)
}
You have to call the present inside the completion handler of the dismiss.
func readerDidCancel(_ reader: QRCodeReaderViewController) {
weak var presentingViewController = self.presentingViewController
self.dismiss(animated: true, completion: {
presentingViewController?.present(ClockInOrOutViewController(), animated: true, completion: nil)
})
}
If this does not work, it means your presenting view controller has also been removed somehow. (dismissed/popped?)
You can't present view controller while other view controller is dismissing and also present on dismissing view controller.
You can do something like this:
func readerDidCancel(_ reader: QRCodeReaderViewController) {
let presenting = self.presentingViewController
dismiss(animated: true, completion: {
presenting?.present(ClockInOrOutViewController(), animated: true, completion: nil)
})
}
I have a loading view controller when my app starts, when an animation in this view controller finished I want it to show another view controller and dismiss the view controller with the animation.
The loading view controller is the initial view controller,
I have this code when UIStoryboard.mflMainTabBarViewController(). returns the view controller that I want to present
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
let animationID = anim.value(forKey: "animationID")
if animationID as! NSString == "transform" {
self.present(UIStoryboard.mflMainTabBarViewController(), animated: true, completion: {
_ = self.popoverPresentationController
})
}
}`
But when deinit is never called
deinit {
print("deinit")
}
What is the best way to deinit the first view controller, and making the presenting view controller the root view controller?
When you are using weak reference cycle at that time deinit method is calling. In strong reference cycle deinit not calling. So create weak reference cycle for calling the method.
Also refer this link.
try this.
Use the vc's parent to present.
And dismiss the vc itself.ðŸ¤
self.presentingViewController?.present(UIStoryboard.mflMainTabBarViewController(), animated: true, completion: {
_ = self.popoverPresentationController
})
self.dismiss(animated: false, completion: nil)
or
self.navigationController?.present(UIStoryboard.mflMainTabBarViewController(), animated: true, completion: {
_ = self.popoverPresentationController
})
self.navigationController?.popViewController(animated: false)
If you are 100% sure that self will never be nil, then just use
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
let animationID = anim.value(forKey: "animationID")
if animationID as! NSString == "transform" {
self.present(UIStoryboard.mflMainTabBarViewController(), animated: true, completion: { [unowned self] in
_ = self.popoverPresentationController
})
}
}`
weak and unowned are the same. Except one thing. Unlike weak we’ve seen, unowned does not automatically convert self as optional within the closure block.
As SplitViewController loads, I am showing a Login Screen. On successful login, I need to go back to parent view controller. Somehow dismissal is not working for me. Here is the code:
ParentViewController:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if !appDelegate.loggedIn {
self.performSegueWithIdentifier("loginScreen", sender: self)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
Child ViewController:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.loggedIn = true
self.dismissViewControllerAnimated(true, completion: nil)
The dismissal part never works. It just hangs on Login Screen.
Try one of the following:
1) remove self. keep only dismissViewControllerAnimated(true, completion: nil)
or remove self. and make it:
2) presentingViewController.dismissViewControllerAnimated(true, completion: nil)
or remove self. and try:
3) presentedViewController.dismissViewControllerAnimated(true, completion: nil)
Try this in your parent view controller:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if !appDelegate.loggedIn {
let loginVC: UIViewController = self.storyboard!.instantiateViewControllerWithIdentifier("LoginViewController") as UIViewController
loginVC = UIModalTransitionStyle.CoverVertical
self.parentViewController?.presentViewController(loginVC, animated: true, completion: nil)
}
}
You're instantiating the new view controller by its own name rather than by the segue name.
I am trying to dismiss a ViewController in swift by calling dismissViewController in an IBAction
#IBAction func cancel(sender: AnyObject) {
self.dismissViewControllerAnimated(false, completion: nil)
println("cancel")
}
#IBAction func done(sender: AnyObject) {
self.dismissViewControllerAnimated(false, completion: nil)
println("done")
}
I could see the println message in console output but ViewController never gets dismissed. What could be the problem?
From you image it seems like you presented the ViewController using push
The dismissViewControllerAnimated is used to close ViewControllers that presented using modal
Swift 2
navigationController.popViewControllerAnimated(true)
Swift 4
navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)
I have a solution for your problem. Please try this code to dismiss the view controller if you present the view using modal:
Swift 3:
self.dismiss(animated: true, completion: nil)
OR
If you present the view using "push" segue
self.navigationController?.popViewController(animated: true)
if you do this i guess you might not get println message in console,
#IBAction func cancel(sender: AnyObject) {
if(self.presentingViewController){
self.dismissViewControllerAnimated(false, completion: nil)
println("cancel")
}
}
#IBAction func done(sender: AnyObject) {
if(self.presentingViewController){
self.dismissViewControllerAnimated(false, completion: nil)
println("done")
}
}
In Swift 3.0 to 4.0 it's as easy as typing this into your function:
self.dismiss(animated: true, completion: nil)
Or if you're in a navigation controller you can "pop" it:
self.navigationController?.popViewController(animated: true)
embed the View you want to dismiss in a NavigationController
add a BarButton with "Done" as Identifier
invoke the Assistant Editor with the Done button selected
create an IBAction for this button
add this line into the brackets:
self.dismissViewControllerAnimated(true, completion: nil)
Use:
self.dismiss(animated: true, completion: nil)
instead of:
self.navigationController.dismissViewControllerAnimated(true, completion: nil)
From Apple documentations:
The presenting view controller is responsible for dismissing the view controller it presented
Thus, it is a bad practise to just invoke the dismiss method from it self.
What you should do if you're presenting it modal is:
presentingViewController?.dismiss(animated: true, completion: nil)
If you presenting a controller without a Navigation Controller, you can call the following code from a method of the presented controller.
self.presentingViewController?.dismiss(animated: true, completion: nil)
If your ViewController is presented modally, optional presentingViewController will be not nil and the code will be executed.
Based on my experience, I add a method to dismiss me as extension to UIViewController:
extension UIViewController {
func dismissMe(animated: Bool, completion: (()->())?) {
var count = 0
if let c = self.navigationController?.viewControllers.count {
count = c
}
if count > 1 {
self.navigationController?.popViewController(animated: animated)
if let handler = completion {
handler()
}
} else {
dismiss(animated: animated, completion: completion)
}
}
}
Then I call this method to dismiss view controller in any UIViewController subclass. For example, in cancel action:
class MyViewController: UIViewController {
...
#IBAction func cancel(sender: AnyObject) {
dismissMe(animated: true, completion: nil)
}
...
}
Since you used push presented viewController, therefore, you can use
self.dismiss(animated: false, completion: nil)
Don't create any segue from Cancel or Done to other VC and only write this code your buttons #IBAction
#IBAction func cancel(sender: AnyObject) {
dismiss(animated: false, completion: nil)
}
So if you wanna dismiss your Viewcontroller use this. This code is written in button action to dismiss VC
#IBAction func cancel(sender: AnyObject) {
dismiss(animated: true, completion: nil)
}
Here is the one way to dismiss present view controller and move back to previous view controller. You can do this through Storyboard only.
Open Storyboard
Right click on Cancel button and drag it to previous view controller, where you want to move back to previous controller
Now release the right click and you can see some actions which performs on cancel button
Now choose "popover present" option from list
Now you can dismiss your current view by click on cancel button
Please try this, It's working with me.
Second Way - Use - navigationController.popViewControllerAnimated(true)
Best luck..
For reference, be aware that you might be dismissing the wrong view controller. For example, if you have an alert box or modal showing on top of another modal. (You could have a Twitter post alert showing on top of your current modal alert, for example). In this case, you need to call dismiss twice, or use an unwind segue.
Try this:
#IBAction func close() {
dismiss(animated: true, completion: nil)
}
If you using the present method in the parent VC then you should call this function, to dismiss the child VC use this
self.dismiss(animated: true, completion: nil)
if you calling child VC by using push method, to dismiss the child VC use this
self.navigationController?.popViewController(animated: true)
If you are presenting a ViewController modally, and want to go back to the root ViewController, take care to dismiss this modally presented ViewController before you go back to the root ViewController otherwise this ViewController will not be removed from Memory and cause Memory leaks.
In Swift 3.0
If you want to dismiss a presented view controller
self.dismiss(animated: true, completion: nil)
In Swift 4.1 and Xcode 9.4.1
If you use pushViewController to present new view controller, use this
self.navigationController?.popViewController(animated: false)
#IBAction func back(_ sender: Any) {
self.dismiss(animated: false, completion: nil)
}