2

I want to add a tap event to my CollectionViewCell and to pass there my cell with the data it has. How can I achieve this? Should this event be handled by my ViewController or by CollectionViewCell?

My ViewController:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
    cell.imgImage.image = imageArray[indexPath.row]
    cell.url = "xhini"

    return cell
}

My CollectionViewCell:

class CollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var imgImage: UIImageView!
    var url: String = "url"
}

enter image description here

M1X
  • 4,971
  • 10
  • 61
  • 123

2 Answers2

5

Implement UICollectionViewDelegate and then you can use following method in the ViewController to react to selecting a cell:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let image = imageArray[indexPath.row]
    // do stuff with image, or with other data that you need
}

Don't forget to set the delegate where you set a data source:

collectionView.dataSource = self
// add this line:
collectionView.delegate = self

UPDATE

Or if you are using a storyboards, you want to set it using storyboards the same way as you set a dataSource for the dataSource of the tableView:

enter image description here

UPDATE 2

Your tap gesture recognizer cancels event for the collection view, so to deal with this, just uncomment the line tap.cancelsTouchesInView = false, and it will work:

    //Looks for single or multiple taps.
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
    //Uncomment the line below if you want the tap not not interfere and cancel other interactions.
    tap.cancelsTouchesInView = false
    view.addGestureRecognizer(tap)
Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
  • I add a simple print statement and it does nothing. You mean I should attach here a tap event or smth? – M1X Feb 04 '18 at 19:37
  • 1
    @rexhin dont forget to set the delegate to self: `collectionView.delegate = self` – Milan Nosáľ Feb 04 '18 at 19:38
  • where should I add this line? inside my `func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let image = imageArray[indexPath.row] // do stuff with image, or with other data that you need }` – M1X Feb 04 '18 at 19:45
  • 1
    @rexhin no, not at all. I think `viewDidLoad` is the best place.. find where you set the data source (where you have line `collectionView.dataSource = self`), and add it there – Milan Nosáľ Feb 04 '18 at 19:47
  • 1
    @rexhin : I suggest you go through Apple docs or perhaps a good UICollectionView tutorial or for that matter, tutorial on delegates as to how they are used and where to set them. – Nitish Feb 04 '18 at 19:48
  • I do not have that line. I do not have a `collectionView` instance at all. I have just an array of UIImages. if you want to check my full project you can check it here: https://gitlab.com/rexhin/ios-kida.git @MilanNosáľ – M1X Feb 04 '18 at 19:50
  • 1
    @rexhin add it to `viewDidLoad`, or add the delegate through the storyboard by linking the `delegate` of the collection view to the `viewController` (the same way you did with dataSource) - I'll update the answer to include a screenshot – Milan Nosáľ Feb 04 '18 at 19:54
  • 1
    @rexhin : As per the code you have shared there is no UICollectionView. I only guess I can make is that you have directly bind the collectionView from storyboard without creating IBOutlet for that. So there are two ways : 1. Set delegate and dataSource from storyboard. 2. Assign IBOutlet to UICollectionView and link it to storyboard and then set delegate and dataSource as Milan has suggested – Nitish Feb 04 '18 at 19:54
  • 1
    @rexhin I updated the question, just link it using storyboards – Milan Nosáľ Feb 04 '18 at 19:56
  • I have something like that but I do not have an instance for that on my file. something like `collectionView`. I updated my question with an image of what i currently have @Nitish @Milan – M1X Feb 04 '18 at 19:59
  • 1
    @rexhin it seems that the delegate is linked.. still not getting that "tap" text printed? – Milan Nosáľ Feb 04 '18 at 20:00
  • nope, i have a print there but i get nothing, `func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("tap") }` – M1X Feb 04 '18 at 20:03
  • @rexhin : Found out the issue. Check my answer – Nitish Feb 04 '18 at 20:12
  • 1
    Thanks a lot. that was funny. the line was already there but commented out – M1X Feb 04 '18 at 20:18
1

I saw your code which you shared in the above answer by @Milan and figured out the reason.
You have added a tap gesture on viewDidLoad of ViewController :

let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
view.addGestureRecognizer(tap)  

This makes the UICollectionView's didSelectItemAt not getting called.
So comment this code and it should work.
For this gesture, you have to find another approach

Nitish
  • 13,845
  • 28
  • 135
  • 263
  • 1
    you recommend him to break other functionality to fix his current issue.. how does this help? – Milan Nosáľ Feb 04 '18 at 20:15
  • Thank you but I have to accept @MilanNosáľ answer because of this reason. :) – M1X Feb 04 '18 at 20:17
  • 1
    If you want to get awarded the accepted answer, you can have it. I solved OP's question. Regarding gesture, I would be happy to help if he faces the issue. BTW, it should be OP who should be worried :) – Nitish Feb 04 '18 at 20:18
  • 1
    @rexhin : Not a problem. Milan's answer was absolutely correct from implementation point of view and should be awarded. Glad I could help. – Nitish Feb 04 '18 at 20:20
  • Those lines you told me to remove are used to close the keyboard. If the user clicks everywhere else except the keyboard the keyboard is closed. – M1X Feb 04 '18 at 20:20
  • 1
    @rexhin : This should help you. Check the accepted answer : https://stackoverflow.com/questions/40365971/how-to-add-tap-gesture-to-uicollectionview-while-maintaining-cell-selection – Nitish Feb 04 '18 at 20:23
  • 1
    Yes, I had that line there before asking this question but for some reason it was commented out – M1X Feb 04 '18 at 20:24