iOS
UIScrollView
Swift
UICollectionViewCell

UICollectionViewCellに配置したUIScrollViewのタッチイベントをUICollectionViewCellにシュッと送る

More than 1 year has passed since last update.

問題

UICollectionViewCellの上にUIScrollViewを配置すると、UIScrollViewがそこでタッチイベントを止めてしまい、通常であればタップ時に呼ばれるUICollectionViewのdelegateメソッド didSelectItemAtIndexPathなどが呼ばれなくなります。しばらく困っていましたがスマートな解決策を見つけたので共有します。

情報源:http://stackoverflow.com/questions/14298650/uicollectionviewcell-with-uiscrollview-cancels-didselectitematindexpath

対策

UIScrollViewは内部にpanGestureRecognizerなるプロパティを抱えており、ここでタッチイベントを検出して、スクロール操作を行っているようです。
で、このpanGestureRecognizerをCellのcontentViewに貼り付け、かつUIScrollViewの userInteractionEnabledfalseにすると、通常どおりスクロールしつつ、タップ時にもdidSelectItemAtIndexPathが呼ばれるようになります。

コード

とりあえずUICollectionViewControllerのcellForItemAtIndexPathで上記の対策を行う例です。
Cellに貼ったUIScrollViewはタグで取り出していますが、実際はUICollectionViewCellをサブクラス化した方がよいかと思います。

CollectionViewController.swift
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
}