TableViewCell管理のグッドプラクティス
Table,TableViewのCellはどのように管理していますか?
愚直に実装して,后から追加の要件が降って来たときに,DataSourceが目も当てられない状态になっていませんか?
ではの记事では,TableViewのCellを良い感じに取り回すためのグッドプラクティスについてサンプルを交えて绍介したいと思います。
叩きとなるサンプルとして,TODOアプリを作成することを考えましょう。
要件
- 一番上にプロフィールのセクションを表示
- カテゴリごとのTODOタスクを并べる
- 各カテゴリにはヘッダーを设ける
この要件のTODOアプリを,
- 単纯に実装
- 中间表现を作成
- 抽象化
という3Stepで见ていきたいと思います。
単纯に実装していくと,以下のようになるかと思います。
こんなにシンプルな要件なのにもう70行ですね…
辛いこと
- DataSourceのそれぞれのメソッドで开关文(或其他文)が乱立してしまい,DRYじゃない
- 查看のレイアウトが変わった际の影响范囲が大きい
そこで,表示されるデータと表示するTableViewの间の中间表现として,
各节,行でTableViewに何を表示するかを表现する
二重配列 (外侧がsection,构成がrowを表す入れ子配列)を定义することで,上记の辛いことを解消していきたいと思います。
これにより,
numberOfSections
-
numberOfRowsInSection
-
titleForHeaderInSection
-
cellForRowAt
で毎回indexPathによる分岐を作る必要がなくなりました。
分岐の处理が共通化されて70行→ 55行とだいぶスッキリしましたね。
TableViewの状态を表す中间表现を二重配列として切り出すことができました。
Data,他の全てのDataSourceにおいて同じような处理を何度も书いていくのも面倒なので,これらを抽象化した衬底クラスStructuredTableCellDataSourceを作ります。
Table,TableViewの剖面,行を表す构造体を定义します。
そして,二重配列として表现していたTableViewの状态を, TableCellSectionの配列として持つStructuredTableCellDataSource を定义します。
UITableViewDataSourceの处理を共通化していきます。
(このあたりは先ほどとやっていることはほとんど同じですね)
Cell,Cellの构成处理はまるっと抽象化できないので,次のように少し工夫してあげる必要があります。
このように,Cellの构筑だけconfigureCellメソッドに逃がし,この基底クラスをoverrideさせたクラスの中で実装します。
したとは新しく作成したDataSourceにStructuredTableCellDataSourceを継承させ,表示したいデータを突っ込んでいきます。
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
ありがとうございました。