Swift 4 - Fatal error: Index out of range

2019-09-19 10:04发布

问题:

I need help for finalize my code in Swift 4: I want to shuffle my questions array, but it always crashes after one time and shows this message:

"Fatal error: Index out of range".

Here is my code:

class ThirdViewController: UIViewController {
    var questions = ["A", "B", "C", "D", "E"]
    var answers = [["1","2","3"],["2","1","3"],["3","2","1"],["1","3","2"],["2","3","1"]]

    // Variables
    var rightAnswerPlacement:UInt32 = 0
    var shuffled = [String]();
    let randomNumber = Int(arc4random() % 5)

    // Label Question
    @IBOutlet weak var Label: UILabel!

    // Buttons
    @IBAction func Button(_ sender: UIButton) {
        if (sender.tag == Int(rightAnswerPlacement)) {
            print ("RIGHT")
            newQuestion()
        }
        else {
            print ("WRONG")
            newQuestion()
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        self.navigationController?.isNavigationBarHidden = true
        newQuestion()
    }

    // Functions
    func newQuestion() {
        Label.text = questions[randomNumber]   // ----------> Fatal error: Index out of range !!! -------------------------------------------------------------
        rightAnswerPlacement = arc4random_uniform(3)+1

        for _ in 0..<questions.count {
            let randomNumber = Int(arc4random_uniform(UInt32(questions.count)))
            shuffled.append(questions[randomNumber])
            questions.remove(at: randomNumber)
        }

    // Create a Button
    var Button:UIButton = UIButton()
    var x = 1
    for i in 1...3 {
        Button = view.viewWithTag(i) as! UIButton
        if (i == Int(rightAnswerPlacement)) {
            Button.setTitle(answers[randomNumber][0], for: .normal)
        }
        else {
            Button.setTitle(answers[randomNumber][x], for: .normal)
            x = 2
        }
    }
}

It seems there is a problem with my variable randomNumber but I don't understand how to fix it. I have seen similar questions on the forum but no answer which resolves my problem.

回答1:

The problem is that when you delete a member of an array while going trough that same array in a for loop, the array.count decreases, and you inevitably get index out of range error.

The common solution of this problem is to go through an array from end to beginning, using the reversed() function of CountableRange:

for _ in (0..<questions.count).reversed(){

    //YOUR CODE
}


回答2:

arc4random() returns a random number in the range of 0 to 4 294 967 295

drand48() returns a random number in the range of 0.0 to 1.0

arc4random_uniform(N) returns a random number in the range of 0 to N - 1

try let randomNumber = Int(arc4random_uniform(5))