Pierce Munro
Pierce Munro

Reputation: 21

I have an sigabbt error that says this Terminating app due to uncaught exception 'NSInvalidArgumentException'

Hello I am trying to complete the element quiz app on the Develop in swift explorations booklet on iBooks for Xcode, and I keep getting 2 constant errors that won't go away whenever I press the "show answer" button the app just crashes and gives me this error'

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ElementQuiz.ViewController showAnswer:]: unrecognized selector sent to instance 0x7fddca6059f0'

here is my code

import UIKit
enum Mode {
    case flashCard
    case quiz
}
enum State {
    case question
    case answer
    case score
}
class ViewController: UIViewController,
UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
        
    }
    
    let elementList = ["Carbon", "Gold", "Chlorine", "Sodium"]
    var currentElementIndex = 0
    var state: State = .question
    var answerIsCorrect = false
    var correctAnswerCount = 0
    var mode: Mode = .flashCard {
        didSet {
            updateUI()
        }
    }
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var answerLabel: UILabel!
    
    @IBAction func showAnswer() {
        state = .answer
        updateUI()
    }
    @IBAction func next(_ sender: Any) {
        if currentElementIndex == elementList.count {
            currentElementIndex = 0
            if mode == .quiz {
                state = .score
                updateUI()
                return
            }
        }
        state = .question
        
        updateUI()
    }
    @IBOutlet weak var modeSelector: UISegmentedControl!
    
    @IBOutlet weak var textField: UITextField!
    
    @IBAction func switchModes(_ sender: Any) {
        if modeSelector.selectedSegmentIndex == 0 {
            mode = .flashCard
        } else {
            mode = .quiz
        }
        var mode: Mode = .flashCard {
            didSet {
                updateUI()
            }
        }
    }
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        let textFieldContents = textField.text!
        
        if textFieldContents.lowercased() == elementList[currentElementIndex].lowercased() {
            answerIsCorrect = true
            correctAnswerCount += 1
        } else {
            answerIsCorrect = false
        }
        state = .answer
        
        updateUI()
        
        return true
    }

    func updateFlashCardUI(elementName: String) {
        textField.isHidden = false
        textField.resignFirstResponder()
        if state == .answer {
            answerLabel.text = elementName
            } else {
                answerLabel.text = "?"
            }
        modeSelector.selectedSegmentIndex = 0
        }
    func updateQuizUI(elementName: String) {
        textField.isHidden = false
        switch state {
        case .question:
            textField.text = ""
            textField.becomeFirstResponder()
        case .answer:
            textField.resignFirstResponder()
        case .score:
            textField.isHidden = true
            textField.resignFirstResponder()
        }
        switch state {
        case .question:
            answerLabel.text = " "
        case .answer:
            if answerIsCorrect {
                print("Correct!")
            } else {
                print("Incorrect!")
            }
            
        case .score:
            answerLabel.text = ""
            print("Your score is \(correctAnswerCount) out of \(elementList.count).")

        }
        if state == .score {
            displayScoreAlert()
        }
        modeSelector.selectedSegmentIndex = 1
    }
    func updateUI() {
        let elementName =
           elementList[currentElementIndex]
        let image = UIImage(named: elementName)
        imageView.image = image
        if state == .answer {
            answerLabel.text = elementName
        } else {
            answerLabel.text = "?"
        }
        switch mode {
        case .flashCard:
            updateFlashCardUI(elementName: elementName)
        case .quiz:
            updateQuizUI(elementName: elementName)
        }
    }
    func displayScoreAlert() {
        let alert = UIAlertController(title: "Quiz Score", message: "Your score is\(correctAnswerCount)out of \(elementList.count).", preferredStyle: .alert)
        let dismissAction = UIAlertAction(title: "OK", style: .default, handler: scoreAlertDismissed(_:))
        alert.addAction(dismissAction)
        
        present(alert, animated: true, completion: nil)
    }
    func scoreAlertDismissed(_ action: UIAlertAction) {
        mode = .flashCard
    }
    }

another error is when I press flash cards then quiz then back to flashcards the app crashes and gives me this error

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ElementQuiz.ViewController textField:]: unrecognized selector sent to instance 0x7fb402d028a0'

can anyone help me fix these errors? thanks

Upvotes: 2

Views: 588

Answers (1)

Alex Walczak
Alex Walczak

Reputation: 1396

Observe that in the error

Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '-[ElementQuiz.ViewController showAnswer:]: unrecognized selector 
sent to instance 0x7fddca6059f0'

your program was expecting -[ElementQuiz.ViewController showAnswer:] to be a valid method.

However, you implemented this method:

@IBAction func showAnswer() {
   state = .answer
   updateUI()
}

which in Objective-C is -[ElementQuiz.ViewController showAnswer] not: -[ElementQuiz.ViewController showAnswer:].

You should instead use the following function, possibly changing sender and Any? to something more appropriate.

@IBAction func showAnswer(_ sender: Any?) {
   state = .answer
   updateUI()
}

Upvotes: 2

Related Questions