UICollectionView の UICollectionReusableView の位置がおかしい時
class SampleListViewController: UIViewController, UICollectionViewDatasource, UICollectionDelegate { @IBOutlet weak var collectionView: UICollectionView! { didSet { collectionView.register( UINib(nibName: "FooterIndicatorView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "FooterIndicatorView" ) } } var footerIndicatorView: UICollectionReusableView! . . . func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { guard kind == UICollectionElementKindSectionFooter else { return UICollectionReusableView() } if footerIndicatorView != nil { footerIndicatorView = collectionView.dequeueReusableSupplementaryView( ofKind: kind, withReuseIdentifier: "FooterIndicatorView", for: indexPath ) } return footerIndicatorView } }
UICollectionView のフッターにローディングインジケータを表示したくて、上記の用に実装していたとします。
インジケータのアニメーションを操作するために、インジケータのインスタンスが生成されたらプロパティに保持しています。
また、インジケータのインスタンスを毎回生成するのが勿体無いと思って、インスタンスが作られていなかったら (nil だったら) dequeue してプロパティに格納して以降はそれを使い回すというように実装していました。
位置がおかしい
この時、 インジケータがセクションの最後のセルのすぐ下に表示されずに、常に UICollectionView の最上部 (しかもセルに被って) 表示されてしまうというバグに遭遇しました。
対応
色々試していたところ、インスタンスが作られていなかったら (nil だったら)
という if 文を消して、毎回 dequeue するようにしたら、意図した通りに表示されました。
なぜ?
Apple のドキュメントを読んでみたのですが、関係ありそうなことは書いていなかったので (たぶん) 、とりあえずライフサイクル的にダメなんだろうなあという感じでした。