問題
UICollectionViewCellの上にUIScrollViewを配置すると、UIScrollViewがそこでタッチイベントを止めてしまい、通常であればタップ時に呼ばれるUICollectionViewのdelegateメソッド didSelectItemAtIndexPath
などが呼ばれなくなります。しばらく困っていましたがスマートな解決策を見つけたので共有します。
対策
UIScrollViewは内部にpanGestureRecognizer
なるプロパティを抱えており、ここでタッチイベントを検出して、スクロール操作を行っているようです。
で、このpanGestureRecognizer
をCellのcontentView
に貼り付け、かつUIScrollViewの userInteractionEnabled
をfalse
にすると、通常どおりスクロールしつつ、タップ時にもdidSelectItemAtIndexPath
が呼ばれるようになります。
コード
とりあえずUICollectionViewControllerのcellForItemAtIndexPath
で上記の対策を行う例です。
Cellに貼ったUIScrollViewはタグで取り出していますが、実際はUICollectionViewCellをサブクラス化した方がよいかと思います。
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
let scrollView = cell.viewWithTag(1) as UIScrollView
scrollView.userInteractionEnabled = false
cell.contentView.addGestureRecognizer(scrollView.panGestureRecognizer)
return cell
}