0
  1. Add a collectionview into a view Add the view into a

  2. backgroundview(UIView)

  3. Add tapGestureRecognizer to the backgroundView

The select event of collectionview can not be triggered when tap a cell,It always trigger the tap event of backgroundview

let backgroundView = UIView(frame: sender.window!.bounds)
    backgroundView.backgroundColor = UIColor.yellowColor()

    let blueView = BlueView(frame: CGRect(x: 300, y: 200, width: 300, height: 400))
    backgroundView.addSubview(blueView)
    sender.window!.addSubview(backgroundView)
    backgroundView.userInteractionEnabled = true

    let gesture = UITapGestureRecognizer(target: blueView, action: "tapGestureRecognizer")
    gesture.delegate = blueView
    backgroundView.addGestureRecognizer(gesture)

..........

    let cv = UICollectionView(frame: CGRect(x: 100, y: 0, width: 100, height: 340), collectionViewLayout: layout)
    cv.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
    cv.dataSource = self

    blueView.addSubview(cv)

Who know the reason?

Leo
  • 795
  • 1
  • 10
  • 29

2 Answers2

1

The problem is that adding a UIGestureRecognzer to the superview affects the touch events in its subviews as well. To avoid that, you need to implement the following delegate method of UIGestureRecognzer and negate the UIGestureRecogniser's touch action by returning false.

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
{
    var view = gestureRecognizer.view
    if view.tag != 100 //Set a tag for the backgroundview
    {
        return false
    }
    return true
}

EDIT

Looking through your code, I doubt you haven't set the UICollectionView's delegate. You have just set the DataSource. The didselect method is a delegate method, not dataSource. Try adding the following right below you set the UICollectionView's dataSource:

cv.delegate= self
Harikrishnan
  • 6,759
  • 12
  • 54
  • 107
  • Where did you implement the delegate method? – Harikrishnan Dec 02 '15 at 06:01
  • I implement the delegate for in the class which contains gesture.delegate = self. And it it called actually and return false when tap a cell, but it does not trigger the didselect event of collection view – Leo Dec 02 '15 at 06:27
0

I think that you answered your question.

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)

It's a delegate method from UICollectionView, so when you make a UIView with recognizer inside cell it takes the touches and won't pass them through and so collection view won't call its delegate methods.

If you want possible solutions, there are a lot:

1) If you need only custom logic inside your cell, when somebody clicked cell, you can just override selected inside cell and add your logic here:

class Cell: UICollectionViewCell {
    override var selected: Bool {
        didSet {

        }
    }
}

2) You can create delegate method that is called from your tap recognizer selector or notification:

func tapGestureRecognizer() {
    NSNotificationCenter.defaultCenter().postNotificationName("TappedRecognizer", object: nil)
}

class YourController: UIViewController {

    override func viewDidLoad() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "tappedRecognizer", name: "TappedRecognizer", object: nil)
    }

    func tappedRecognizer() {
        // your code here
    }
}

3) I suppose its possible to pass your touches through your view to cell, so it will call delegate method of UICollectionView, then you should override pointInside method for UITapGestureRecognizer, you can search a lot of code on this topic, like this

Community
  • 1
  • 1
katleta3000
  • 2,400
  • 1
  • 14
  • 22