読者です 読者をやめる 読者になる 読者になる

そーす

福岡在住のプログラマ

UICollectionViewで最下部での追加読み込みを実装する

f:id:saburesan:20160427075732p:plain

アプリの仕様で * UICollectionViewの最下部で追加読み込みをする * 読み込みの際に最下部でインジケータを表示する * 追加がない場合はインジケータを消す

という仕様、あるあるですよね。

方法はいくつかあるのですが、私が一番しっくりきた実装を載せます。

Footerでイベントの取得、インジケータの表示をする

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        if kind == UICollectionElementKindSectionFooter {
            let view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, type: FooterReusableView.self, indexPath: indexPath)
            view.showIndicator()
            page += 1
            fetchItems { view.hideIndicator() }
            return view
        } else {
            return UICollectionReusableView()
        }
    }

func fetchItems(completion: () -> () = { }) {
..
 }


collectionView.dequeueReusableSupplementaryViewOfKindは自作のextensionです

    func dequeueReusableSupplementaryViewOfKind<CellType: UICollectionReusableView>(kind: String, type: CellType.Type, indexPath: NSIndexPath) -> CellType {
        return dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: NSStringFromClass(type), forIndexPath: indexPath) as! CellType
    }



Footerでの追加読み込みの良い所はviewDidLoad後のアイテムがない場合でも呼ばれるので、読み込みのトリガーを1箇所にできるのはいいなと思います。

注意すべき点

Footerでの読み込みの注意すべき点はcollectionView.reloadData()を呼ぶタイミングです。

collectionView.reloadData()が呼ばれるとviewForSupplementaryElementOfKindも場合によっては再度呼ばれます。

もし、追加読み込みの要素が無い時にcollectionView.reloadData()を呼んでしまうと

最下部までスクロール→Footerが呼ばれる→追加読み込み→要素無しでreload→Footerが呼ばれる→…

という無限ループに陥ってしまうので注意が必要です。