如何从位于集合视图单元格内的步进器获取选定的IndexPath?

时间:2018-12-12 06:44:37

标签: ios swift uicollectionview uicollectionviewcell uistepper

我有一个收集视图,该收集视图在收集视图单元格中具有步进器,用于增加如下图所示的产品数量。

enter image description here

我需要知道,当我单击集合视图单元格上的步进器时。我怎么知道那个集合视图单元格的indexPath.item?这样我可以在View控制器中使用选定的indexPath修改数据?

所以如果我在第二个单元格中更改步进器,我将始终获得indexPath.item = 1

我以前认为indexPath来自下面的didSelectItemAt方法。但是当我点击集合视图单元格中的步进器时,似乎不会触发didSelectItemAt方法。

  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    }

所以我想我可以从cellForRowAt IndexPath并使用协议委托模式获取indexPath。这是我做的方法,我得到了错误的indexPath

因此,如果我在第二个单元格中更改步进器,我将不会总是获得indexPath.item = 1,它可以是2,3,0等。

这是视图控制器代码:

class WishListVC: UIViewController, ListProductCellDelegate {

    var products = [Product]()
    var selectedProduct : Product?

     // method from ListProductCellDelegate
    func stepperButtonDidTapped(at selectedIndexPath: IndexPath, stepperValue: Int) {

        // get selectedIndexPath
        // perform some action based on selectedIndexPath

    }
}

extension WishListVC : UICollectionViewDataSource, UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return products.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as? ListProductCell else { return UICollectionViewCell()}


        cell.productData = products[indexPath.item]
        cell.indexPath = indexPath // I send the indexPath to the cell.
        cell.delegate = self

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        selectedProduct = products[indexPath.item]
        performSegue(withIdentifier: WishListStoryboardData.SegueIdentifiers.toProductVC.rawValue, sender: nil)
    }


}

这是集合视图单元格中的代码:

protocol ListProductCellDelegate {
    func stepperButtonDidTapped( at selectedIndexPath: IndexPath, stepperValue: Int)
}

class ListProductCell: UICollectionViewCell {

    var indexPath: IndexPath?
    var delegate: ListProductCellDelegate?

    var productData : Product? {
        didSet {
            updateUI()
        }
    }

    @IBAction func stepperDidTapped(_ sender: GMStepper) {
        guard let indexPath = indexPath, let collectionView = collectionView else {return}
        self.delegate?.stepperButtonDidTapped(at: indexPath, stepperValue: Int(sender.value))
    }


    func updateUI() {
        // update the UI in cell.
    }
}

3 个答案:

答案 0 :(得分:3)

您可以尝试将tag属性添加到步进器。因此,当您单击步进器时,您可以收听其选择器并确定调用了哪个步进器。标签值应与商品索引相同。

类似这样的东西

cell.stepper.tag = indexPath.row

上面的代码应该放在cellForRowAt委托函数中。

然后在用户点击步进器时调用一个函数并检查标签值

类似这样的东西

func stepperClicked(sender) {
    //check sender.tag value
    //Do something here with the tag value
}

答案 1 :(得分:1)

在Swift中,回调关闭可能是最有效的解决方案。它独立于索引路径,标签,视图层次结构 和协议。

在单元格中添加一个callback属性,该属性传递步进器实例。删除indexPathdelegate。完全不需要该协议。

IBAction调用callback中传递步进器实例

class ListProductCell: UICollectionViewCell {

    var callback: ((GMStepper) -> Void)?

    var productData : Product? {
        didSet {
            updateUI()
        }
    }

    @IBAction func stepperDidTapped(_ sender: GMStepper) {
        callback?(sender)
    }


    func updateUI() {
        // update the UI in cell.
    }
}

cellForItemAt中的控制器中设置闭包并处理回调。该方法中捕获了索引路径。

也不要guard个单元格。强制展开。该代码不得崩溃。如果这样做,则表明存在设计错误。使用guard方式,表格视图将不显示任何内容,而且您也不知道为什么。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WishListStoryboardData.CollectionViewIdentifiers.productSliderCell.rawValue, for: indexPath) as! ListProductCell
    cell.productData = products[indexPath.item]
    cell.callback = { stepper in 
       // handle the callback
    }
    return cell
}

答案 2 :(得分:0)

您拥有步进器,因为它是您的操作方法中的sender。步进器具有一个超级单元,即单元格(您可能必须走上一个以上的超级单元才能到达单元格)。拥有单元格后,您可以调用indexPath(for:)以获取索引路径。做完了

https://developer.apple.com/documentation/uikit/uicollectionview/1618094-indexpath