0

How do I get the index of the "Sheep" I clicked on in a CollectionView made in Xcode with Swift for iOS?

class SheepsOverviewVC: 
UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "class", for: indexPath) as! ClassesCollectionCell
    if(sheeps.count > 0) {
        cell.ClassImageView.image = UIImage(named: sheeps[indexPath.row] as! String)
        cell.SheepName.text = names[indexPath.row] as? String
    }
    return cell
}

I created a Sent Event on the TouchDown via the Gui:

@IBAction func clickingSheep(_ sender: UIButton) {
    print("This will show info about the Sheep")
    print(sender)
}

But the response I get is from the second print:

<UIButton: 0x7f9a63021d20; frame = (50 50; 136 169); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x60800003d260>>

Probably there is some way to figure out which Sheep was clicked, but how do I get that information?

This is how it looks like (other namings then provided in the post): Xcode

user1469734
  • 851
  • 14
  • 50
  • 81
  • Is the `clickingSheep` method in your custom cell class or in your collection view controller class? – rmaddy Aug 16 '17 at 15:14
  • 1
    Assuming `clickingSheep` is defined where the collectionView is created: Possible duplicate of [How to get the indexPath of a UIButton in a UITableViewCell?](https://stackoverflow.com/questions/16229488/how-to-get-the-indexpath-of-a-uibutton-in-a-uitableviewcell) – Ozgur Vatansever Aug 16 '17 at 15:15
  • @OzgurVatansever no, it's not a UiTableView. – user1469734 Aug 16 '17 at 15:40
  • @maddy in the collectionviewcontrollerclass – user1469734 Aug 16 '17 at 15:41
  • @user1469734 OK, then the link by Ozgur is essentially what you need. Just adjust the API used a little for `UICollectionView` instead of `UITableView`. – rmaddy Aug 16 '17 at 15:45
  • @user1469734 doesn't matter. The solution in the link applies to collection views as well. – Ozgur Vatansever Aug 16 '17 at 15:56

2 Answers2

6

One solution is to get the index path of the cell based on the button's location.

@IBAction func clickingSheep(_ sender: UIButton) {
    let hitPoint = sender.convert(CGPoint.zero, to: collectionView)
    if let indexPath = collectionView.indexPathForItem(at: hitPoint) {
        // use indexPath to get needed data
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
2

You can set and check the button property "tag" (if you have the outlet set to the controller)

Here is another easy solution:

Have a new property for the callback.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "class", for: indexPath) as! ClassesCollectionCell
        if(sheeps.count > 0) {
            cell.ClassImageView.image = UIImage(named: sheeps[indexPath.row] as! String)
            cell.SheepName.text = names[indexPath.row] as? String
        }
        cell.callBack = { [weak self] collectionViewCell in 
               let indexPath = collectionView.indexPath(for: collectionViewCell)
               self?.doStuffFor(indexPath)
        } 
        return cell
    }

and on the cell you can have the ibaction

    cell class
    //...

    var callBack : ((UICollectionViewCell?)->Void)?
    //...

    @IBAction func action(_ sender: UIButton) {
         self.callBack?(self)
    }
Durdu
  • 4,649
  • 2
  • 27
  • 47
  • 1
    No, do not add an `indexPath` property to the cell. It will be wrong any time an item is deleted, inserted, or moved in the collection view. It is much better to pass the cell, not the indexPath, as the parameter to the callback. Then the handler can ask the collection view what the index path for the cell is. – rmaddy Aug 16 '17 at 16:01
  • Updated the response. Thx for the observation @rmaddy. – Durdu Aug 17 '17 at 07:56