Search code examples
swiftseguevar

How can I properly send values between classes in Swift?


I've been working on a text based adventure game using Swift. However, I can't seem to change the default values for specific classes.

Below is the code for the class that allows me to select my player class

    import UIKit

    class ClassSelectionController: UIViewController
    {
        //Default class values
        var character = (0, 0, "", 0)

        override func viewDidLoad()
        {
                super.viewDidLoad()
                // Do any additional setup after loading the view.
        }

        //class button actions
        @IBAction func fighterBtn(_ sender: Any)
        {
                character = (50, 60, "Steal Sword", 18)
                performSegue(withIdentifier: "Character", sender: self)
        }

        @IBAction func wizerdBtn(_ sender: Any)
        {
                character = (25, 70, "Staff", 15)
                performSegue(withIdentifier: "Character", sender: self)
        }

        @IBAction func thiefBtn(_ sender: Any)
        {
                character = (30, 60, "Dagger", 18)
                performSegue(withIdentifier: "Character", sender: self)
        }

        @IBAction func archerBtn(_ sender: Any)
        {
                character = (50, 60, "Bow & Arrow", 16)
                performSegue(withIdentifier: "Character", sender: self)
        }


        override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
        {
                //code for segue
                var vc = segue.destination as! ViewController
                vc.finalCharacter = self.character
        }

    }

And this is the class that receives the data for the player class and displays it.

    import UIKit

    class ViewController: UIViewController
    {
            var finalCharacter = (0, 0, "", 0)
            //****************************************
            //Setup for outlets go between these lines
            //****************************************
            @IBOutlet weak var healthLabel: UILabel!
            @IBOutlet weak var damageLabel: UILabel!
            @IBOutlet weak var weaponLabel: UILabel!
            @IBOutlet weak var armorLabel: UILabel!
            @IBOutlet weak var storyLabel: UILabel!
            @IBOutlet weak var actionButton: UIButton!


            @IBOutlet weak var northBtn: UIButton!
            @IBOutlet weak var southBtn: UIButton!
            @IBOutlet weak var eastBtn: UIButton!
            @IBOutlet weak var westBtn: UIButton!

            //****************************************
            //Setup for outlets go between these lines
            //****************************************


            override func viewDidLoad()
            {
                    super.viewDidLoad()
                    // Do any additional setup after loading the view.

                    healthLabel.text = "Health: \(finalCharacter.0)"
                    damageLabel.text = "Damage: \(finalCharacter.1)"
                    weaponLabel.text = "Weapon: " + finalCharacter.2
                    armorLabel.text  = "Armor : \(finalCharacter.3)"
            }

            //****************************************
            //Setup for buttons go between these lines
            //****************************************
            @IBAction func actionButton(_ sender: Any)
            {

            }

            @IBAction func northButton(_ sender: Any)
            {

            }

            @IBAction func southButton(_ sender: Any)
            {

            }

            @IBAction func eastButton(_ sender: Any)
            {

            }

            @IBAction func westButton(_ sender: Any)
            {

            }
    //****************************************
    //Setup for buttons go between these lines
    //****************************************
    }

Even though my code does not currently show it I did put print values in the class buttons just so see if the values have changed when I select a class and I have seen that they do change when the button is pressed. I also poked around in ViewController and changed the finalCharacter values, just to see if that affected anything, which it didn't. So my educated guess is that the problem has to be in ClassSelectionController.

So the main problem is that I will click on the wizard player class, and I'd expect the class stats for the wizard to pop up (I.e. 25, 70, "Staff", 15), but I'll only get the default values that are in the ClassSelectionController (0, 0, "", 0).


Solution

  • What is happening here that you have multiple UIStoryboardSegue named "Character" linked with every button

    so what happens is when you press the button the Segue is called before the Action button and in addition the UIStoryboardSegue is called again (if you place a debugger in the viewDidLoad you would see that it goes there two times).

    Solution

    • Remove all the UIStoryboardSegue linked from the buttons
    • Make a new UIStoryboardSegue from the ClassSelectionController to the next ViewController name it 'Character' see here

    You dont need to change anything from the code but should add a safe check

    override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
        {
            if (segue.identifier == "Character") {
                let vc = segue.destination as! ViewController
                vc.finalCharacter = self.character
            }
        }