-2

I created a single view app with 2 view controllers. In the first view controller, I have a label and 2 buttons that were programmatically created. I have 2 segues from these buttons to the second view controller. I wish that each button carries different information to the second view controller. From creating these buttons and segues programmatically, I haven’t been able to assign the identifier to the segues. So, I can’t use performSegue(withIdentifier: sender:). How can I do this?

First ViewController:

import UIKit

class ViewController: UIViewController {
    var myLabel: UILabel!
    var leftButton: UIButton!
    var rightButton: UIButton!

// bellow are the 2 variable which I’d like to transport into the second ViewController

    var leftButtonText = "I'm the left button."
    var rightButtonText = "I'm the right button."

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let homeNavBar = UINavigationBar()
        homeNavBar.frame = CGRect(x: 0, y: 0, width: 320, height: 45)
        homeNavBar.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(homeNavBar)

        let homeNavItem = UINavigationItem(title: "Home")
        homeNavBar.setItems([homeNavItem], animated: false)


        myLabel = UILabel()
        myLabel.frame = CGRect(x: 165, y: 150, width: 200, height: 42)
        myLabel.text = "Press one of the button bellow!"

        self.view.addSubview(myLabel)

        leftButton = UIButton(type: .custom)
        leftButton.frame = CGRect(x: 80, y: 300, width: 70, height: 70)
        leftButton.backgroundColor = UIColor.cyan
        leftButton.setTitleColor(UIColor.black, for: .normal)
        leftButton.setTitle("Left Button", for: .normal)
        leftButton.layer.cornerRadius = 20
        leftButton.layer.borderWidth = 1
        leftButton.layer.masksToBounds = true
        leftButton.addTarget(self, action: #selector(ViewController.leftButtonAction(_:)), for: .touchUpInside)

        self.view.addSubview(leftButton)

        rightButton = UIButton(type: .custom)
        rightButton.frame = CGRect(x: 240, y: 300, width: 70, height: 70)
        rightButton.backgroundColor = UIColor.cyan
        rightButton.setTitleColor(UIColor.black, for: .normal)
        rightButton.setTitle("Right button", for: .normal)
        rightButton.layer.cornerRadius = 20
        rightButton.layer.borderWidth = 1
        rightButton.layer.masksToBounds = true
        rightButton.addTarget(self, action: #selector(ViewController.rightButtonAction(_:)), for: .touchUpInside)

        self.view.addSubview(rightButton)

        let margins = self.view.layoutMarginsGuide

        homeNavBar.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
        homeNavBar.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
        homeNavBar.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
        myLabel.topAnchor.constraint(equalTo: homeNavBar.bottomAnchor).isActive = true
        leftButton.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
        leftButton.topAnchor.constraint(equalTo: myLabel.bottomAnchor).isActive = true
        rightButton.topAnchor.constraint(equalTo: myLabel.bottomAnchor).isActive = true
        rightButton.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true

    }

    @objc func leftButtonAction (_ sender: UIButton) {
        let segueSecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "idSecond")
        self.show(segueSecondViewController, sender: nil)
        print("I'm activated by the left button.")
    }

    @objc func rightButtonAction (_ sender: UIButton) {
        let segueSecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "idSecond")
        self.show(segueSecondViewController, sender: nil)
        print("I'm activated by the right button.")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Second ViewController:

import UIKit

class SecondViewController: UIViewController {
    var mySecondLabel: UILabel!
    var mySecondLabelText = "I'm the second page."
    var closeButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let secondNavBar = UINavigationBar()
        secondNavBar.frame.size = CGSize(width: 320, height: 45)
        secondNavBar.translatesAutoresizingMaskIntoConstraints = false
        let secondNavItem = UINavigationItem(title: "Second page")
        secondNavBar.setItems([secondNavItem], animated: false)

        self.view.addSubview(secondNavBar)

        mySecondLabel = UILabel()
        mySecondLabel.frame = CGRect(x: 165, y: 200, width: 200, height: 42)
        mySecondLabel.backgroundColor = UIColor.yellow
        mySecondLabel.textColor = UIColor.black
        mySecondLabel.text = "\(mySecondLabelText)"
        mySecondLabel.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(mySecondLabel)

        closeButton = UIButton(type: .custom)
        closeButton.frame = CGRect(x: 10, y: 50, width: 50, height: 50)
        closeButton.backgroundColor = UIColor.red
        closeButton.setTitleColor(UIColor.black, for: .normal)
        closeButton.setTitle("Close", for: .normal)
        closeButton.layer.cornerRadius = 30
        closeButton.layer.borderWidth = 1
        closeButton.layer.masksToBounds = true
        closeButton.addTarget(self, action: #selector(SecondViewController.closeButtonAction(_:)), for: .touchUpInside)

        self.view.addSubview(closeButton)

        let margins = self.view.layoutMarginsGuide

        secondNavBar.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
        secondNavBar.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
        secondNavBar.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
        closeButton.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
        closeButton.topAnchor.constraint(equalTo: secondNavBar.bottomAnchor).isActive = true
        mySecondLabel.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
        mySecondLabel.topAnchor.constraint(equalTo: closeButton.bottomAnchor).isActive = true
        mySecondLabel.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true

    }

    @objc func closeButtonAction (_ sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
        print("Second page closed.")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}
Xcoder
  • 1,433
  • 3
  • 17
  • 37
  • If both of your viewControllers are in the Storyboard, then see this : https://stackoverflow.com/a/26457259/1630618 – vacawama Mar 31 '18 at 19:49
  • This method is ok but I have 2 buttons created programmatically. So, I can't use it. I'd like to have 2 UIStoryboardSegue objects to use. – Aurel Calin Muth Apr 02 '18 at 14:57
  • You can use it with more than one segue. Just drag out as many as you need and give each one its own identifier. – vacawama Apr 02 '18 at 15:24
  • Ok, but if it should happen that I don't know before how many buttons will exist in my ViewController? – Aurel Calin Muth Apr 02 '18 at 15:56
  • Why does each button need its own segue? The segue really defines the destination view controller and how it is presented. Several buttons can present the same segue, and you'd use the `sender` to differentiate the behavior. Each button would send itself as the sender, and `prepareFor(segue:sender:)` could use the button's `tag` for instance to set up the destination differently. – vacawama Apr 02 '18 at 16:21
  • I resolved. If it isn’t too much, I wish to ask you, how can I know which button I pressed to pass in the new ViewController? – Aurel Calin Muth Apr 02 '18 at 18:12
  • In the @IBAction for your button, pass your button as the sender: `self.performSegue(withIdentifier: "goToSecondVC", sender: sender)`. Then in `prepare(for:sender)`, set a property in the destination VC (`segue.destination`) to `(sender as? UIButton)?.currentTitle`. – vacawama Apr 02 '18 at 18:58
  • It’s that I imagined. Thank you very much! – Aurel Calin Muth Apr 03 '18 at 04:28

1 Answers1

0

You can do it by giving your View Controller an Identifier. This isn't a segue, but it will Instantiate your target VC:

let vc = UIStoryboard(name:"Main", bundle:nil).instantiateViewControllerWithIdentifier("identifier") as! SecondViewController

self.navigationController?.pushViewController(vc, animated:true)

You can set the VC Identifier on the Identity Inspector tab on the StoryBoard.

I just read in the documentation that you can't call the performSegue method if you don't have a segue with an identifier in the Storyboard, so WRT your requirement, you can't do it programmatically.

identifier The string that identifies the triggered segue. In Interface Builder, you specify the segue’s identifier string in the attributes inspector.

Martin Muldoon
  • 3,388
  • 4
  • 24
  • 55