Home > Software design >  Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) func prepare
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) func prepare

Time:01-12

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.identifier {
    case toProductIdentifier: let destination = segue.destination as? ProductViewController
        destination?.configureProduct(for: products[selectedRowIndex.row])
    default: break
    }
}

So I getting this error in line destination?.configureProduct(for: products[selectedRowIndex.row])

And here is a code for func configureProduct but I Don't really think that problem in this func

func configureProduct(for product: instockProduct) {
    DispatchQueue.main.async {
        let brand = product.brand["name"] as? String ?? ""
        self.productBrandLabel.text = brand.uppercased()
        self.productNameLabel.text = product.name
        self.productPriceLabel.text = product.price.stringValue
    }
}

CodePudding user response:

You are instantiating indexPath with empty value indexPath = IndexPath(), and propably not using indexPath that is provided to you by tableView, therefore the error. I reproduced in Playground your code with simplified example and get the same error.

Try checking if the didSelectItemAt function is triggered properly and you are truly assigning to selectedRowIndex variable the indexPath returned from UITableView and not using the precreated IndexPath() value.

recreated your error

CodePudding user response:

The problem is that the outlets are not connected (yet) in the destination view controller during prepare(for segue.

You need a temporary property in ProductViewController and configure the outlets in viewDidLoad

var product : Product! // replace Product with the real type

func viewDidLoad() {
    super.viewDidLoad()
    DispatchQueue.main.async {
        let brand = product.brand["name"] as? String ?? ""
        self.productBrandLabel.text = brand.uppercased()
        self.productNameLabel.text = product.name
        self.productPriceLabel.text = product.price.stringValue
    }
}

and replace prepare(for segue with

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.identifier {
        case toProductIdentifier: 
           let destination = segue.destination as! ProductViewController
           let product = sender as! Product
           destination.product = product
        default: break
    }
}

The product item is passed in the sender parameter. Delete selectedRowIndex and replace didSelectItem with

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    let product = products[indexPath.row]
    print(product.name) 
    collectionView.deselectItem(at: indexPath, animated: true)         
    self.performSegue(withIdentifier: toProductIdentifier, sender: product) 
} 
  •  Tags:  
  • Related