0

I am writing a basic iOS app to test my Swift knowledge and keep on practicing. In my app the user types a name for a baby, then turns a switch either on or off to set the gender/sex and also change the system color. After that, the name is used to fill in a UITextView, named "firstWords", in the following block of code:

// Save name entered into text field
@IBAction func saveSettings(_ sender: UIButton) {
    nameLabel.text = nameTextField.text
    if nameTextField.text == "" {
        showMessage()
        nameLabel.text = "Baby Name"
    }
    nameTextField.resignFirstResponder()
    let nameHolder: String! = nameLabel.text
    if boyGirlSwitch.isOn {
        let sex = ("boy", "his", "he", "Boy", "His", "He")
    } else {
        let sex = ("girl", "her", "she", "Girl", "Her", "She")
    }
    firstWords.text = "Wow, " + nameHolder + " has so much to look forward to!" + (sex.5) + " will do so many great things!"
}

I keep getting an error at the tuple (sex.5) inside firstWords that says: "Use of unresolved identifier 'sex'"

As I understand it, the constant sex is declared within the if statement and the compiler does go through it either way, so it does get identified and declared. QUESTION: Why am I getting the error?

Thanks in advance! Here's a screenshot of my code as well: Screenshot of block of code as described above, including the compiler/build-error

Junsan
  • 1
  • 2

1 Answers1

2

This is a scope issue. sex is only available within the else clause.

You can fix it like this

// Save name entered into text field
@IBAction func saveSettings(_ sender: UIButton) {
    nameLabel.text = nameTextField.text
    if nameTextField.text == "" {
        showMessage()
        nameLabel.text = "Baby Name"
    }
    nameTextField.resignFirstResponder()
    let nameHolder: String! = nameLabel.text
    var sex : (String, String, String, String, String, String)
    if boyGirlSwitch.isOn {
        sex = ("boy", "his", "he", "Boy", "His", "He")
    } else {
        sex = ("girl", "her", "she", "Girl", "Her", "She")
    }
    firstWords.text = "Wow, " + nameHolder + " has so much to look forward to!" + (sex.5) + " will do so many great things!"
}

this way sex is defined within the scope of the whole IBAction and will be available in the end.

you could also skip one condition if you pre-declare it with a default:

// Save name entered into text field
@IBAction func saveSettings(_ sender: UIButton) {
    nameLabel.text = nameTextField.text
    if nameTextField.text == "" {
        showMessage()
        nameLabel.text = "Baby Name"
    }
    nameTextField.resignFirstResponder()
    let nameHolder: String! = nameLabel.text
    var sex = ("girl", "her", "she", "Girl", "Her", "She")
    if boyGirlSwitch.isOn {
        sex = ("boy", "his", "he", "Boy", "His", "He")
    }
    firstWords.text = "Wow, " + nameHolder + " has so much to look forward to!" + (sex.5) + " will do so many great things!"
}

There is actually a nice article about variable scope on Wikipedia: https://en.wikipedia.org/wiki/Scope_(computer_science)

Sebastian Flückiger
  • 5,525
  • 8
  • 33
  • 69
  • Thanks for the quick answer, Sebastian, but it does not work in my case... Inside the `if` statements, I now get the error: "Cannot assign String, String, String... to a value of String... But I tried something else that seemed to work fine - declaring the variable before the `if` and then assigning values right there. It gets changed later on and then using the `(sex.5)` call inside `firstWords` works 100%. Thanks anyway for your help – Junsan Jun 13 '17 at 08:08
  • @Junsan fixed my answer to declare varialbe with correct type. i would recommend the 2nd version however. In general this is a very error-prone way of handling such a situation. I would strongly suggest you use defined structs in such a case :) – Sebastian Flückiger Jun 13 '17 at 10:26
  • Yes I hope to improve my coding as I learn further. Thanks for the advice – Junsan Jun 13 '17 at 12:31