Search code examples
iosswiftuicollectionviewdidselectrowatindexpath

didSelectItemAtIndexPath not called with multiple collection views on same screen


I have 2 collection views on the same screen, and I have the data source and delegate implemented for both in the same view controller. However, the delegate methods such as didSelectItemAtIndexPath is only called for one.

Other info:

  • Both collection views have a cell with an image.
  • AllowSelection and UserInteractionEnabled is set to true in both collection views
  • User interaction enabled on the images
  • Delegate and data source are set on the storyboard from both collection views to the view controller
  • Collection views are displayed properly

Both collection views have the same setup, yet only one delegate works. Would you have any clues what could be setting this up?

The collection views are inside a view that has a scroll view. Could this be somehow related?

EDIT 2:

Project with the same problem: https://github.com/iagomr/ProblemWithAutoLayout

EDIT 1:

Somehow this has to do with autolayout constraints, because if I pin the bottom collection view to the bottom of the screen instead of the bottom of other collection view, it starts working.

This is all due to the fact that I need to build a tall screen, and added everything into a view inside a scroll view 1000 points tall.

Code:

//MARK: - CollectionView Delegate
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    println("Called")
}

//MARK: - CollectionView DataSource
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    if collectionView == thisCV {
        return 1

    } else if collectionView == thisOtherCV{
        return 1
    }
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    if collectionView == "thisCV" {
        if let thisCell = collectionView.dequeueReusableCellWithReuseIdentifier("thisCell", forIndexPath: indexPath) as? thisCollectionViewCell {

            thisCell.image = image

            return thisCell
        }

    } else if collectionView == "thisOtherCV"{
        if let thisOtherCell = collectionView.dequeueReusableCellWithReuseIdentifier("thisOtherCell", forIndexPath: indexPath) as? OtherCollectionViewCell {

            thisOtherCell.image = image

            return thisOtherCell
        }
    }

    return UICollectionViewCell()
}

Solution

  • I can confirm that didSelectItem is not getting called. If constant for top-bottom constraint between two collection views is changed from 501 to 0 it is working.

    This problem is most likely related to the fact that you have two scroll views (collection views) inside of another scroll view. Overall, I would say, that you should modify your UI. I would suggest two ways of fixing it

    Using single collection view

    Use just one collection view with different sections for different content. Also, do NOT embed it in the scroll view - collection view already has a scroll view so you should be able to scroll easily. You can also dequeue different class of cells for different sections so you should be able to do everything which you want to do now.

    If you want a starting point, here is a good tutorial which should help you with that.

    Using scroll view

    If you want to setup your UI in Interface Builder remove both collection views and simply add all of your UI inside of scroll view. Place UIButton in places where you want clicking to produce action.

    You can even assign the same action to each button and then differentiate which one was triggered by assigning custom tags to each of them.