-1

I have a problem, Xcode gives me this error "EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode==0*0)" while I'm trying to make my buttons delete indexes in my array, "shoppingList". Please help me and tell me what i did wrong so i can improve later on.

//
//  ViewController.swift
//  ShoppingList
//
//  Created by Petr Chrastek on 29/03/16.
//  Copyright © 2016 ACS. All rights reserved.
//
class ViewController: UIViewController {
    @IBOutlet weak var labelText: UILabel!
    @IBOutlet weak var label0: UILabel!
    @IBOutlet weak var label1: UILabel!
    @IBOutlet weak var label2: UILabel!
    @IBOutlet weak var label3: UILabel!
    var shoppingList = ["eggs", "milk", "cake", "sugar"]

    @IBAction func remove0(sender: UIButton) {
        shoppingList.removeAtIndex(0)
    }

    @IBAction func remove1(sender: UIButton) {
        shoppingList.removeAtIndex(1)
    }

    @IBAction func remove2(sender: UIButton) {
        shoppingList.removeAtIndex(2)
    }

    @IBAction func remove3(sender: UIButton) {
        shoppingList.removeAtIndex(3)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let str: String? = shoppingList[0]
        let str1: String? = shoppingList[1]
        let str2: String? = shoppingList[2]
        let str3: String? = shoppingList[3]
        let count = shoppingList.count
        labelText.text? = "you are missing \(count) items"
        if str != nil {
            label0.text? = "\(str)"
        } else {
            label0.text? = "empty"
        }
        if str1 != nil {
            label1.text? = "\(str1)"
        } else {
            label1.text? = "empty"
        }
        if str2 != nil {
            label2.text? = "\(str2)"
        } else {
            label2.text? = "empty"
        }
        if str3 != nil {
            label3.text? = "\(str3)"
        } else {
            label3.text? = "empty"
        }
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
David Berry
  • 40,941
  • 12
  • 84
  • 95
A. stein
  • 87
  • 1
  • 1
  • 7

1 Answers1

0

After you delete the first item from your list, shoppingList will only have 3 items in it, so accessing shoppingList[3] will crash (remember with 3 items only 0..<2 are valid.

The easiest way to resolve the problem is to use the following pattern so you're checking the count to make sure indices are valid before using them.

if shoppingList.count > 0 {
    label0.text = shoppingList[0]
} else {
    label0.text = "empty"
}

if shoppingList.count > 1 {
    label1.text = shopingList[1]
} else {
    label1.text = "empty"
}

I've made some additional changes as well, such as not pointless using string interpolation to turn a String into the same String, since [String][n] will always return a String (never a String?) there's no need to deal with the Optionals

You'll have similar problems (in fact, probably what you're running into now) when you try to:

shoppingList.removeAtIndex(3)

the second time, since 3 is no longer a valid index, instead, use:

if shoppingList.count > 3 {
    shoppingList.removeAtIndex(3)
}
David Berry
  • 40,941
  • 12
  • 84
  • 95
  • Generally speaking, `Array` index bounds are strictly checked, unlike `Dictionary` where typically a missing index will simply return `nil` – David Berry Mar 29 '16 at 19:18