Search code examples
swift3xcode8ios10.3

Unresolved Identifier error within @IBAction func


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


Solution

  • 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)