UICollectionView を使う際、以下のようにセルを再利用していました
// CustomCell.swift class CustomCell: UICollectionViewCell { static func nib() -> UINib { return UINib(nibName: String(describing: self), bundle: nil) } static func reuseIdentifier() -> String { return String(describing: self) } } // CustomViewController.swift ... // セルを登録 collectionView.register( CustomCell.nib(), forCellWithReuseIdentifier: CustomCell.reuseIdentifier() ) ... // 登録したセルを取り出す collectionView.dequeueReusableCell( withReuseIdentifier: CustomCell.reuseIdentifier(), for: indexPath )
この .nib
.reuseIdentifier
をカスタムセルごとに書くのが面倒になったので、今回は protocol extension を使って解消しようと思います
(UICollectionView については以下)
https://developer.apple.com/documentation/uikit/uicollectionview
Protocol Extension
Protocols — The Swift Programming Language (Swift 5.1)
protocol を拡張して実装し、適合した型に提供することができます
拡張してコードを共通化するなら通常の extension でも良いのですが、こちらはより柔軟で再利用性が高いです
先程の .nib
.reuseIdentifier
メソッドを protocol extension で実装します
// 1. protocol を定義 protocol ReusableProtocol { static func nib() -> UINib static func reuseIdentifier() -> String } // 2. protocol を実装 extension ReusableProtocol { static func nib() -> UINib { return UINib(nibName: String(describing: self), bundle: nil) } static func reuseIdentifier() -> String { return String(describing: self) } } // 3. UICollectionView に適合 extension UICollectionViewCell: ReusableProtocol {}
これで、 UICollectionViewCell のサブクラスで .nib
.reuseIdentifier` メソッドが使えるようになりました
通常の extension と比較して
再利用性が高い
protocol なので、他のクラスに適合させるだけで再利用できます
UITableViewCell で再利用したい...場合でも、コードは以下の1行
extension UITableViewCell: ReusableProtocol {}
対象を限定できる
protocol を実装する際に where
を使うことで、対象を絞ることができます
UICollectionViewCell でのみ使いたい際は以下のようにする
extension ReusableProtocol where Self: UICollectionViewCell { static func nib() -> UINib { return UINib(nibName: String(describing: self), bundle: nil) } static func reuseIdentifier() -> String { return String(describing: self) } }
そのほか
デメリットとしては、そのまま objc から使えない点でしょうか...(objc 側で定義してあげれば使える?)
extension をうまく使えば UICollectionView の .register / .dequeue も簡略化できそうです
名前空間とやりすぎに注意しつつ使おうと思います