UICollectionViewでscrollToItemAtIndexPathのcompletionがとれない

## 要約
左右にスクロールできる`UICollectionView`のスクロールアニメーション完了後に処理を行いたい

- `UIView`や`CATransaction` でやってみるもうまくいかない
- `UIScrollViewDelegate`利用する方法で対処できるが根本的解決ではない
- 0.3秒の遅延実行や`NSTimer`の利用でも対処できるが、現実的ではない。

どなたか解決方法ご存知のかたいらっしゃいましたらコメントお願いいたします。 :bow: 

## 本題
左右にスクロールできる`UICollectionView`の`scrollToItemAtIndexPath:atScrollPosition:animated:`のアニメーション完了後に処理を行いたい

### サンプル
```swift
self.collectionView.scrollToItemAtIndexPath(lastItemIndexPath,
    atScrollPosition: UICollectionViewScrollPosition.Right,
    animated: true) // このアニメーション時間もできたら調整したい
completionBlock() // これをスクロールアニメーション終了後に行いたい
}
```

### 環境
- Xcode 7.1
- Swift 2.1
- Mac OSX Yosemite

## Pattern 1: `UIView.animateWithDuration:animations:completion:`（失敗）
```swift
UIView.animateWithDuration(10, animations: { () -> Void in
    self.collectionView.scrollToItemAtIndexPath(self.indexPathForLastItem,
        atScrollPosition: UICollectionViewScrollPosition.Right,
        animated: false)
    }) { (finished: Bool) -> Void in
        completionBlock()
}
```
結果:
10秒間`collectionView`のアイテムが消えている状態が続いた後、およそ0.3秒でスクロールされる。
10秒待った後に`completionBlock`が実行される。

なお `animated`に`true`を指定した場合、
10秒指定は無視され、およそ0.3秒でスクロール。
`completionBlock`は即時実行される。


## Pattern 2: `CATransaction`（失敗）
```swift
CATransaction.begin()
CATransaction.setAnimationDuration(10)
CATransaction.setCompletionBlock(completionBlock)
self.collectionView.scrollToItemAtIndexPath(self.indexPathForLastItem,
    atScrollPosition: UICollectionViewScrollPosition.Right,
    animated: false)
CATransaction.commit()
```

結果:
アニメーションなしで即スクロール。
`completionBlock`は即時実行される。

なお `animated`に`true`を指定した場合
10秒指定は無視され、およそ0.3秒でスクロール
`completionBlock`は即時実行される

## Pattern 3: `setContentOffset` で指定（失敗）
結果:
同様にコントロールできず。
（めんどくさいんでサンプル割愛）

## Pattern 4: もう0.3秒待っちゃえよ（一応成功）
```swift
self.collectionView.scrollToItemAtIndexPath(self.indexPathForLastItem,
    atScrollPosition: UICollectionViewScrollPosition.Right,
    animated: true)
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.3 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
    completionBlock()
}
```
結果:
目標の動作達成
いや、そりゃ動くけども...

## Pattern 5: `NSTimer`でちょっとずつ動かす（多分成功）
いやだ :no_good: 

## Pattern 6: `UIScrollViewDelegate`の`scrollViewDidEndScrollingAnimation:`を使う（成功）
ViewController側で
`UIScrollViewDelegate`の`scrollViewDidEndScrollingAnimation:`を利用して`completionBlock`を実行

```swift
// Property
private var isScrollingToLast = false
private var scrollLastCompletion: (() -> Void)?

func scrollToLastItem() {
    self.collectionView.scrollToItemAtIndexPath(self.indexPathForLastItem, atScrollPosition: .Right, animated: true)
    let rightEdge = self.collectionView.contentOffset.x + self.collectionView.frame.size.width
    if rightEdge >= self.collectionView.contentSize.width {
        // Already scrolled to last item
        completionBlock()
    } else {
        self.isScrollingToLast = true
        self.scrollLastCompletion = completionBlock
    }
}

// MARK: - UIScrollViewDelegate
func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
    if self.isScrollingToLast {
        self.scrollLastCompletion?()
        self.isScrollingToLast = false
        self.scrollLastCompletion = nil
    }
}
```
すでに右端までスクロールしている場合`scrollViewDidEndScrollingAnimation:`が実行されないので計算が必要

一応完了後に実行できているので目標は達成しているものの、
ViewController側でコントロールしなければならないのでできれば避けたい。

## 参考
http://stackoverflow.com/questions/16597360/animation-duration-for-uicollectionview-selectitematindexpathanimatedscrollpos
http://stackoverflow.com/questions/4404745/change-the-speed-of-setcontentoffsetanimated

## TODO
- gifを載せる