毎月恒例の関モバ #8に参加しました.
今回は,UITableView
で複数のレイアウトを持つセルをどう扱うかというトークをしました.
骨子としては,UITableView
で複数のレイアウトを持つセルを実装するとき,いくつかの方法がありますがコードでレイアウトをいじるとAuto Layoutの指定が複雑になるので,レイアウトのパターンごとにxibを分けるといいというものです.
複数のxibを使うことについて少し補足
UITableView
においてxibを増やす場合,xibの登録やセルのリユースなどセルを使うための決め事が複雑になることが問題になります.
セルを複数のView Controllerで使いまわしたい場合,それぞれで同じ実装をすることが強いられます.
そこで,このトークでは実装パターンとしてEntryCellRepresentable
のようなprotocolを使うことを紹介しました.
紹介したものは単純で以下のような実装です.
※ この例ではEntryCell
に対して複数のxib(EntryCell.xibとEntryCellWithImage.xibの2つ)が存在し,それぞれでレイアウトを定義することを前提としています(画像があるパターンと無いパターンです).
protocol EntryCellRepresentable { var tableView: UITableView! { get } func registerEntryCell() func dequeueEntryCell(entry: Entry, forIndexPath indexPath: NSIndexPath) -> EntryCell } extension EntryCellRepresentable { func registerEntryCell() { ["EntryCell", "EntryCellWithImage"].forEach { tableView.registerNib(UINib(nibName: $0, bundle: nil), forCellReuseIdentifier: $0) } } func dequeueEntryCell(entry: Entry, forIndexPath indexPath: NSIndexPath) -> EntryCell { let reuseIdentifier = entry.hasImage ? "EntryCellWithImage" : "EntryCell" let cell = tableView.dequeueCellReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! EntryCell cell.entry = entry return cell } }
EntryCellRepresentable
はEntryCell
を使ううえでの規約(全てのパターンのxibを漏れなくregisterNib
する,dequeueCellReusableCellWithIdentifier
し,モデルであるEntry
をセットする)を隠蔽します.
UITableView
を使うとき,多くはUITableViewController
のサブクラスを使うことでしょう.
UITableViewController
はプロパティにvar tableView: UITableView!
を持っていますので,EntryCellRepresentable
を指定するだけでprotocolに適合させることができます.
したがって,EntryCell
を表示するclass EntriesViewController: UITableViewController
はこのように実装できます.
class EntriesViewController: UITableViewController, EntryCellRepresentable { override func viewDidLoad() { super.viewDidLoad() registerEntryCell() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let entry = entries[indexPath.row] return dequeueEntryCell(entry, forIndexPath: indexPath) } }
UITableView
を自分で追加する場合はvar tableView: UITableView!
を実装するだけです.
このような工夫によって,使いまわしやすさを維持しつつxibを分けることが可能です.