I have collection view that has stepper inside the collection view cell used to increase the number of product like the image below.
I need to know, when I click a stepper on a collection view cell. how do I know the indexPath.item
of that collection view cell? so I can modify the data using the selected indexPath in the View controller?
so If I change the stepper in the second cell, I will always get indexPath.item = 1
I previously think that the indexPath
will come from didSelectItemAt
method below. but it seems the didSelectItemAt
method will not be triggered when I tap the stepper inside the collection view cell.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
so I think I can get indexPath from cellForRowAt IndexPath
and using protocol delegate pattern. here is the method I made, and I got the wrong indexPath
So If I change the stepper in the second cell, I will NOT always get indexPath.item = 1 , It can be 2,3,0 etc.
here is the view controller code:
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)
}
}
and here is the code in the collection view cell:
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.
}
}
You can try adding tag
property to the stepper. So when you click on the stepper you can listen to its selector and determine which stepper was called. The tag value should be same as the item index.
Something like this
cell.stepper.tag = indexPath.row
Above code should go inside the cellForRowAt delegate function.
and then when user taps on the stepper call a function and check the tag value
Something like this
func stepperClicked(sender) {
//check sender.tag value
//Do something here with the tag value
}