Search code examples
swiftxcodesegue

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) func prepare


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
    }
}

Solution

  • 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 cell = sender as! ProductCollectionViewCell
               let indexPath = collectionView.indexPath(for: cell)!
               destination.product = products[indexPath.item]
            default: break
        }
    }
    

    Edit:

    Obviously you connected the cell to the segue rather than the controller. In this case the cell is passed in the sender parameter and didSelectItemAt is not being called. Delete selectedRowIndex and delete also the entire didSelectItemAt method

    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) 
    }