TableViewCell管理のグッドプラクティス

Table,TableViewのCellはどのように管理していますか?

愚直に実装して,后から追加の要件が降って来たときに,DataSourceが目も当てられない状态になっていませんか?

ではの记事では,TableViewのCellを良い感じに取り回すためのグッドプラクティスについてサンプルを交えて绍介したいと思います。


叩きとなるサンプルとして,TODOアプリを作成することを考えましょう。

要件

  • 一番上にプロフィールのセクションを表示
  • カテゴリごとのTODOタスクを并べる
  • 各カテゴリにはヘッダーを设ける

この要件のTODOアプリを,

  1. 単纯に実装
  2. 中间表现を作成
  3. 抽象化

という3Stepで见ていきたいと思います。

単纯に実装していくと,以下のようになるかと思います。

表示するタスクの配列をプロパティとして持つDataSourceを作る
科の数
部ごとの行の数
科のヘッダータイトル
各行に表示する单元格

こんなにシンプルな要件なのにもう70行ですね…

辛いこと

  • DataSourceのそれぞれのメソッドで开关文(或其他文)が乱立してしまい,DRYじゃない
  • 查看のレイアウトが変わった际の影响范囲が大きい

そこで,表示されるデータと表示するTableViewの间の中间表现として,
各节,行でTableViewに何を表示するかを表现する
二重配列 (外侧がsection,构成がrowを表す入れ子配列)を定义することで,上记の辛いことを解消していきたいと思います。

表示するタスクを二重配列として持つDataSourceを作る

これにより,

  • numberOfSections
  • numberOfRowsInSection
  • titleForHeaderInSection
  • cellForRowAt

で毎回indexPathによる分岐を作る必要がなくなりました。

科の数
部ごとの行の数
科のヘッダータイトル
各行に表示するCell

分岐の处理が共通化されて70行→ 55行とだいぶスッキリしましたね。

TableViewの状态を表す中间表现を二重配列として切り出すことができました。

Data,他の全てのDataSourceにおいて同じような处理を何度も书いていくのも面倒なので,これらを抽象化した衬底クラスStructuredTableCellDataSourceを作ります。

Table,TableViewの剖面,行を表す构造体を定义します。

TableCellSection.swift
TableCellRow.swift

そして,二重配列として表现していたTableViewの状态を, TableCellSectionの配列として持つStructuredTableCellDataSource を定义します。

表示するタスクをTableCellSectionの配列として持つStructuredTableCellDataSourceを作る

UITableViewDataSourceの处理を共通化していきます。
(このあたりは先ほどとやっていることはほとんど同じですね)

科の数
部ごとの行の数
科のヘッダータイトル

Cell,Cellの构成处理はまるっと抽象化できないので,次のように少し工夫してあげる必要があります。

各行に表示するCell

このように,Cellの构筑だけconfigureCellメソッドに逃がし,この基底クラスをoverrideさせたクラスの中で実装します。

したとは新しく作成したDataSourceにStructuredTableCellDataSourceを継承させ,表示したいデータを突っ込んでいきます。

抽象化したDataSourceを継承させたクラス

55行→ 32行とさらに短くなりました!


参考にしたもの

kickstarterのossにあるValueCellDataSource.swiftを参考にしています。
(见ていただけるとわかりますが,やっていることはほとんど同じです)

kickstarter / ios-oss

适用于iOS的Kickstarter。 随时随地将新想法带入生活。 – kickstarter / ios-oss

github.com

また,ライブラリDataSourceKitではこの记事で述べたような抽象化を违う手法で简洁に再现し,宣言的にCellを定义できるようにしています。

ishkawa / DataSourceKit

UICollectionView和UITableView的声明性可测试数据源。 – ishkawa / DataSourceKit

github.com

ある程度抽象化は必要ですが,

  • 今いるチームがどこまで抽象化したいか
  • 后から入ってきた人が理解・纳得できるか

を考えることがいずれにしても大切ですね。

ドはンプルコードは以下のリポジトリにあげていますので気になる方は见てみてください。

摇滚名/ CellManagement

TableView单元管理良好做法示例。 通过创建一个…来为rockname / CellManagement开发做出贡献

github.com

ありがとうございました。