How to Handle an index out of range error crash

Hello:


I am working with a tutorial that will help me in designing my Mac Os app.


I have the following code that is generating and error "index out of ragne" crash: on line 35.

The array is in a .plist file with 5 items in each array [0,1,2,3,4].


Lines 28 - 38 is supposed to do the following:


  1. It removes all items in the pop-up button, getting rid of the Item1 and Item2 entries.
  2. It adds an item for every product, showing its title.
  3. It selects the first product and the first item of the pop-up button. This makes sure that everything is consistent.


Why is it generating an "index out of range" error when lines 31, 32 adds back the items to the array?



import Cocoa

class ViewController: NSViewController {
    private var overviewViewController: OverviewController?
    private var detailViewController: DetailViewController?
   
    private var products = [Product]()
    var selectedProduct: Product?
   
    @IBAction func valueChanged(_ sender: NSPopUpButton) {
       
        detailViewController?.selectedProduct = selectedProduct
        if let bookTitle = sender.selectedItem?.title,
            let index = products.firstIndex(where: {$0.title == bookTitle}) {
            selectedProduct = products[index]
        }
        overviewViewController?.selectedProduct = selectedProduct
    }
   
    @IBOutlet weak var productsButton: NSPopUpButton!
   
    override func viewDidLoad() {
        super.viewDidLoad()
       
        if let filePath = Bundle.main.path(forResource: "Products", ofType: "plist") {
            products = Product.productsList(filePath)
        }
        //1
        productsButton.removeAllItems()
        //2
        for product in products {
            productsButton.addItem(withTitle: product.title)
        }
        //3
        selectedProduct = products [0]//index out of range error
       
        productsButton.selectItem(at: 0)// Do any additional setup after loading the view.
    }
   
    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }
   
    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
       
        guard let tabViewController = segue.destinationController
            as? NSTabViewController else { return }
       
        for controller in tabViewController.children {
           
            if let controller = controller as? OverviewController {
                overviewViewController = controller
                overviewViewController?.selectedProduct = selectedProduct
            }
            else if let controller = controller as? DetailViewController {
                detailViewController = controller
                detailViewController?.selectedProduct = selectedProduct
            }
        }
       
    }
   
}

Accepted Reply

It seems you have a key error:


Line 22 print statement: productList ##START## [["Imagename": iOS10, "Price": 54.99, "Name": iOS by tutorials, "Description": Learn New Ios, "Audience": Intermediate]] productList ##END##


key is Imagename


But line 39 it is ImageName


          init?(dictionary: [String: Any]) {
            guard let title = dictionary["Name"] as? String,
              let audience = dictionary["Audience"] as? String,
              let descriptionText = dictionary["Description"] as? String,
              let price = dictionary["Price"] as? NSNumber,
              let imageName = dictionary["ImageName"] as? String else {
                return nil
            }



Imagename is not ImageName


Hence, guard let fails, hence you return nil.


Fix that (use Imagename in the guard statement) and it will work

Replies

Look at the following debug output:

...

Initialization of Product failed with ["Price": 54.99, "Imagename": swift_apprentice,...


That means all the initializer call to `Product` has failed, which causes the line `products.append(product)` is not executed.


---

Use of Codable as in :

results in error: 1. Type 'Product' does not conform to protocol 'Encodable'

2. Type 'Product' does not conform to protocol 'Decodable'


Do you think I have shown the code without testing? Why are you hiding some parts of the code, please try the exact code I have shown.