How to dismiss ViewController in Swift?
Asked Answered
I

20

244

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")
}

random image of a segue

I could see the println message in console output but ViewController never gets dismissed. What could be the problem?

Isosceles answered 10/7, 2014 at 5:2 Comment(3)
How did you present the view controller?Forney
I did the mapping by setting a segue - "show", see the attached screenshot.Isosceles
Try to use modal. If you use push, you should dismiss it with the pop method of the navigation controller.Forney
B
460

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)
Barcellona answered 10/7, 2014 at 5:41 Comment(3)
How would you do it for a 'Show Detail' segue?Fabaceous
For Swift 2.2 navigationController!.popViewControllerAnimated(true)Apsis
For Swift 3 navigationController!.popViewController(animated: true)Turtledove
S
197

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)
Strigil answered 10/7, 2014 at 5:35 Comment(5)
Thanks, but still the same result, it does not dismiss the ViewControllerIsosceles
How is this different to the method the OP used?Forney
Conversation is useless if you don't react to my questions.Forney
_ = self.navigationController?.popViewController(animated: true)Increate
For me 'dismiss' is taking me back to the login screen, pre where the tab controller is definedFauve
R
22

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")
  }    
}
Rejection answered 10/7, 2014 at 5:49 Comment(1)
#30840735. Any Help,please?I am stuck at that for so long who still cant find solutionElf
G
20

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)
Giulietta answered 20/10, 2016 at 5:4 Comment(1)
dismiss not working, because I'm using pushViewController. Only self.navigationController?.popViewController(animated: true) working.Surratt
A
15
  1. embed the View you want to dismiss in a NavigationController
  2. add a BarButton with "Done" as Identifier
  3. invoke the Assistant Editor with the Done button selected
  4. create an IBAction for this button
  5. add this line into the brackets:

    self.dismissViewControllerAnimated(true, completion: nil)
    
Antheridium answered 19/1, 2015 at 16:36 Comment(0)
M
15

Use:

self.dismiss(animated: true, completion: nil)

instead of:

self.navigationController.dismissViewControllerAnimated(true, completion: nil)
Milomilon answered 16/7, 2015 at 10:53 Comment(2)
add a ! to the navigationController and it works for meImpudent
@naturalc: Be aware that if navigationController is nil and you put !, the app will crashMilomilon
P
12

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)
Philip answered 5/12, 2018 at 8:47 Comment(0)
W
11

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.

Watersick answered 30/6, 2016 at 21:36 Comment(0)
J
7

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)
   }
   ...
}
Jamey answered 3/2, 2017 at 19:21 Comment(0)
B
6

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)
  }
Benzidine answered 25/3, 2017 at 14:2 Comment(1)
While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.Chitarrone
P
6

Since you used push presented viewController, therefore, you can use

self.dismiss(animated: false, completion: nil)
Pharmaceutical answered 3/7, 2020 at 19:35 Comment(0)
C
5

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)
}
Codycoe answered 19/10, 2016 at 10:29 Comment(0)
R
5

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)
Riker answered 4/6, 2020 at 11:58 Comment(0)
V
4

Here is the one way to dismiss present view controller and move back to previous view controller. You can do this through Storyboard only.

  1. Open Storyboard
  2. Right click on Cancel button and drag it to previous view controller, where you want to move back to previous controller
  3. Now release the right click and you can see some actions which performs on cancel button
  4. Now choose "popover present" option from list
  5. 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..

Vinificator answered 10/7, 2014 at 5:46 Comment(2)
#30840735. Any Help,please?I am stuck at that for so long who still cant find solutionElf
This is wrong. You are never dismissing the view you are instead presenting a new view controller on top of the current one, causing a memory leak. This will most likely get your app rejected from the app store.Devoice
W
3

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.

Wombat answered 6/4, 2016 at 12:11 Comment(0)
E
3

Try this:

@IBAction func close() {
  dismiss(animated: true, completion: nil)
}
Evocation answered 5/4, 2019 at 14:29 Comment(1)
The method called "dismissViewController" it only takes a single parameter, which I suppose would look like to dismiss animated to previous view, this is the simplest solution.Evocation
G
2

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.

Ghostwrite answered 21/7, 2016 at 6:20 Comment(0)
S
2

In Swift 3.0

If you want to dismiss a presented view controller

self.dismiss(animated: true, completion: nil)
Seesaw answered 22/8, 2017 at 7:12 Comment(0)
S
2

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)
Surratt answered 17/7, 2018 at 9:46 Comment(1)
Another copy paste answerIllfavored
M
2
@IBAction func back(_ sender: Any) {
        self.dismiss(animated: false, completion: nil)
    }
Milliard answered 14/10, 2019 at 18:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.