How do I programmatically dismiss a view controller?

This is my app design concept:

On launch -

  1. A table view opens with a + button in the nav bar (this works fine)
  2. When the + button is tapped a new table view is created programmatically and opens with a Done button in its nav bar (this works correctly)
  3. User enters data into the table view rows then taps the Done button when finished (this is my problem)

My code for returning the user back to the main table view controller does not function as I would like. Here is my button code:


func doneButtonPressed(sender: UIButton!) {
        /
        /
/
      let message = "You just pressed the Done button."
       
        let alert = UIAlertController(
                    title: "Thank you",
                    message: message,
                    preferredStyle: .Alert)
       
        let action = UIAlertAction(
                    title: "Goodbye",
                    style: .Default,
                    handler: nil)
       
        alert.addAction(action)
*/
        / 
        /
        /
/
        /func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
       
            return mainview()
       
        }
*/
        /
       
        /
        let viewController:UIViewController = UIViewController()
        self.presentViewController(viewController, animated: true, completion: nil)
       
    }



Looking at the code -

If line 18 is active the alert will pop up. The alert is just test code to make certain that my button is actually working and it is.

If both line 18 and 20 are active, the alert will pop up momentarilly then be dismissed. Line 20 causes the pop up to close. The code on line 20 only closes the alert view and that is not what I want to happen. I would like for the user to be returned to the viewController.swift that she came from.


I also tried the code on lines on 32-33 and this simply took the user to a black view. I am sure this happened because this is a blank view and not the ViewController.swift controller that I wanted.


For the sake of clarity: When user taps the + button in the opening table view, this results in a new view, table view, nav bar and Done button that are all created programmatically. There are no segues involved. Much of the code I found in my reseach made reference to segues and that is not what I have.


If someone could point me in the right direction I would be most appreciative.

Thank you!

Answered by junkpile in 157321022

In that case you would just need to keep a reference to the top-level view "v" in a property, and call v.removeFromSuperview() and set it to nil when you are done with it.


But I think presenting a separate table view controller would be more modular / maintainable.

Because of this POS forum software your commented out code does not show. But in any case, if your second view controller was itself presented using presentViewController(), then you just need to call self.dismissViewController(). If you are trying to "go back", you certainly don't want to create and present a brand new view controller.


BTW the fact that you would have to know whether you were being presented modally (in which case you would call dismissViewController) or as a "push" in a navigation controller (in which case you would call popViewController) is a big part of the reason unwind segues were introduced, I think. If you use an unwind segue, your presented/pushed VC doesn't have to know or care. You would just call performSegueWithIdentifier and UIKit will do the rest.

Because of comments that are truncated, your code is hardly readable.


But you have already defined


let alert = UIAlertController(… )


So you should call

self.presentViewController(alert, animated: true, completion: nil)


and not create a new controller with

let viewController:UIViewController = UIViewController()

@junkpile

Thank you for your response.

I did not create my present the table view controller using presentViewController() as you noted. This is how I created the new view, tab bar, table view and Done button. As you will see I have some test constraint code because I am having some iPad constraint issues so I have a switch stmt that I am using to test the constraints with.

And again, for the sake of clairity, once the user taps the + button in the main view controller the resultant views and behavior are done programmatically (or so I think ...). Here is the code.

When the user taps the + button she triggers the following action method:


func getNewTableView() {

        let mainview = self.view

        var tableView: UITableView = UITableView()
        tableView = UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
        tableView.delegate = self
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

        if self.didSetup {return}
        self.didSetup = true

        let v = UIView()
        let v1 = UITableView()
     
        v.backgroundColor = UIColor.grayColor()
        v.translatesAutoresizingMaskIntoConstraints = false
     
        mainview.addSubview(v)
     
        NSLayoutConstraint.activateConstraints([
            NSLayoutConstraint.constraintsWithVisualFormat("H:|-(0)-[v]-(0)-|",
                    options: [],
                    metrics: nil,
                    views: ["v":v]),
            NSLayoutConstraint.constraintsWithVisualFormat("V:|-(0)-[v]-(0)-|",
                    options: [],
                    metrics: nil,
                    views: ["v":v])].flatten().map{$0})
        v.preservesSuperviewLayoutMargins = true  /
     
        /
     
        v1.translatesAutoresizingMaskIntoConstraints = false /
     
        v.addSubview(v1)
        var which : Int {return 1}
     
        switch which {
         
        case 1:
            /
            print("... in case 1: ........./n")
            NSLayoutConstraint.activateConstraints([
                NSLayoutConstraint.constraintsWithVisualFormat("H:|-[v1]-|", options: [], metrics: nil, views: ["v1":v1]),
                NSLayoutConstraint.constraintsWithVisualFormat("V:|-[v1]-|", options: [], metrics: nil, views: ["v1":v1])
                ].flatten().map{$0})
         
        case 2:
            /
            print("... in case 2: ........./n")
            NSLayoutConstraint.activateConstraints([
                v1.topAnchor.constraintEqualToAnchor(v.layoutMarginsGuide.topAnchor),
                v1.bottomAnchor.constraintEqualToAnchor(v.layoutMarginsGuide.bottomAnchor),
                v1.trailingAnchor.constraintEqualToAnchor(v.layoutMarginsGuide.trailingAnchor),
                v1.leadingAnchor.constraintEqualToAnchor(v.layoutMarginsGuide.leadingAnchor)
                ])
         
        case 3:
            /
            /
            print("... in case 3: ........./n")
            NSLayoutConstraint.activateConstraints([
                v1.topAnchor.constraintEqualToAnchor(v.readableContentGuide.topAnchor),
                v1.bottomAnchor.constraintEqualToAnchor(v.readableContentGuide.bottomAnchor),
                v1.trailingAnchor.constraintEqualToAnchor(v.readableContentGuide.trailingAnchor),
                v1.leadingAnchor.constraintEqualToAnchor(v.readableContentGuide.leadingAnchor)
                ])
        default:break
        }   /
     
    }


The following function triggers the getNewTableView, the getNewTabBar and the createDoneButton functions:


@IBAction func getNewTableView(sender: AnyObject) {
        self.getNewTableView()
        self.getNewTabBar()
        self.createDoneButton()
    }


As seen the button tap triggers the getNewTableView, the getNewTabBar and the createDoneButton functions.


I hope the above code will help you understand what and how I have been trying to implement my app. Now all I have to figure out is how to get the user back to the ViewController.swift when she taps the Done button.


I sincerely appreciate your help.

@Claude31


Thank you for your response to my post. I have posted some new code above which hopefully will shed some light on how my app functions - or not!


Thanks again for your help.

Accepted Answer

In that case you would just need to keep a reference to the top-level view "v" in a property, and call v.removeFromSuperview() and set it to nil when you are done with it.


But I think presenting a separate table view controller would be more modular / maintainable.

@junkpile

Thank you very much for your help.

I will implement your suggestions to dismiss the view and think seriously about presenting a separate table view controller as you suggested as well.

I sincerely appreicate your help.

How do I programmatically dismiss a view controller?
 
 
Q