Home > Software engineering >  how to make a show a new controller after closing another controller?
how to make a show a new controller after closing another controller?

Time:12-08

I am new to Swift and want to make a simple application

When the user opens the app, it gets to the FirstViewController where there is 1 Login button, when the user clicks on this button, I present a SecondViewController modally

On the SecondViewController there are text fields and an "Auth button", I want that by clicking on the "Auth Button", the SecondViewController closes and the FirstViewController opens the ThirdViewController

How to do it right?

I do not use storyboard, if it's important

CodePudding user response:

You are "new to Swift" ... you may want to spend more time learning the basics before trying to "make a simple application".

The problem is that, at this point, you don't even know what to ask, or proper terminology.

For example, you say:

  • "gets to the FirstViewController" ... what do you mean "gets to"?
  • "click" instead of "tap"
  • "the SecondViewController closes and the FirstViewController opens the ThirdViewController" ... "close" and "open" are ambiguous terms

I don't mean to sound harsh, but would you try to write a novel before learning the alphabet?

However, here is a quick, very simple example...

We start with FirstViewController as the root controller... button tap presents SecondViewController and sets a closure... button tap in that controller calls the closure, at which point we pass the user entered strings and replace the root controller with ThirdViewController:

class FirstViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemRed
        
        // create a "Login" button
        let btn = UIButton()
        btn.backgroundColor = .darkGray
        btn.setTitleColor(.white, for: .normal)
        btn.setTitleColor(.lightGray, for: .highlighted)
        btn.setTitle("Login", for: [])
        btn.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(btn)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            // center the button in the view
            btn.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            btn.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.75),
            btn.heightAnchor.constraint(equalToConstant: 50.0),
        ])
        
        // add touchUpInside action
        btn.addTarget(self, action: #selector(loginBtnTapped(_:)), for: .touchUpInside)
    }
    
    @objc func loginBtnTapped(_ sender: Any?) -> Void {
        let secondVC = SecondViewController()
        
        // set the closure
        secondVC.theClosure = { [weak self] str1, str2 in
            guard let self = self else { return }
            
            // closure was called from SecondVC,
            //  dismiss it and then show ThirdVC
            self.dismiss(animated: true, completion: {
                let thirdVC = ThirdViewController()
                
                // set the strings
                thirdVC.val1 = str1
                thirdVC.val2 = str2
                
                // replace First VC with Third VC
                UIApplication.shared.windows.first?.rootViewController = thirdVC
                UIApplication.shared.windows.first?.makeKeyAndVisible()
            })
        }
        
        // present the second VC
        self.present(secondVC, animated: true, completion: nil)
    }
    
    
}

class SecondViewController: UIViewController {

    var theClosure: ((String, String) -> ())?
    
    let tf1 = UITextField()
    let tf2 = UITextField()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemGreen

        // stack view to arrange two fields and a button
        let stack = UIStackView()
        stack.axis = .vertical
        stack.spacing = 20
        stack.translatesAutoresizingMaskIntoConstraints = false

        // add text fields to stack view
        [tf1, tf2].forEach { tf in
            tf.borderStyle = .roundedRect
            stack.addArrangedSubview(tf)
        }
        
        // create an "Auth" button
        let btn = UIButton()
        btn.backgroundColor = .darkGray
        btn.setTitleColor(.white, for: .normal)
        btn.setTitleColor(.lightGray, for: .highlighted)
        btn.setTitle("Auth", for: [])
        
        // add button to stack view
        stack.addArrangedSubview(btn)

        view.addSubview(stack)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            // constrain stack view centered horizontally, near top
            stack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            stack.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            stack.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.75),
            btn.heightAnchor.constraint(equalToConstant: 50.0),
        ])

        // add touchUpInside action
        btn.addTarget(self, action: #selector(authBtnTapped(_:)), for: .touchUpInside)
    }
    
    @objc func authBtnTapped(_ sender: Any?) -> Void {
        // get the text from the two fields
        var s1 = tf1.text ?? ""
        var s2 = tf2.text ?? ""
        if s1.isEmpty { s1 = "Field 1 Empty" }
        if s2.isEmpty { s2 = "Field 2 Empty" }

        // call the closure with the two strings
        theClosure?(s1, s2)
    }

}

class ThirdViewController: UIViewController {
    
    var val1: String = ""
    var val2: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBlue
        
        // create a multi-line label
        let label = UILabel()
        label.backgroundColor = .cyan
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(label)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            // constrain the label centered in the view
            label.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            label.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.75),
        ])

        // set label text
        var s: String = "User-entered strings:"
        s  = "\n\n"
        s  = val1
        s  = "\n\n"
        s  = val2

        label.text = s
    }
    
}
  • Related