线程 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

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

所以我在 destination?.configureProduct(for: products[selectedRowIndex.row])

行中收到此错误

这是 func configureProduct 的代码,但我真的不认为这个 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
    }
}

您正在用空值 indexPath = IndexPath() 实例化 indexPath,并且可能没有使用 tableView 提供给您的 indexPath,因此出现错误。我在 Playground 中用简化的示例复制了您的代码,但得到了同样的错误。

尝试检查 didSelectItemAt 函数是否被正确触发,您是否真正将 UITableView 返回的 indexPath 分配给 selectedRowIndex 变量,而不是使用预先创建的 IndexPath() 值.

问题是在 prepare(for segue 期间目标视图控制器中的出口尚未连接(尚未)。

您需要 ProductViewController 中的临时 属性 并在 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
    }
}

并将prepare(for segue替换为

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

编辑:

显然您将 cell 连接到 segue 而不是控制器。在这种情况下,cellsender 参数中传递并且 didSelectItemAt 未被调用。删除 selectedRowIndex 并删除整个 didSelectItemAt 方法

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