RxSwiftとUITableViewの設定は少し分かりづらかったので、ここにまとめてみます。
まず、”SectionModel”というものを作成します。これは、UITableViewをいくつかのセクションに分ける場合の、いくつかのセクションと、そのセクション内のTableViewCellの内容に対応しています。
// ConfigViewSectionModelはSectionModel (RxDatasourcesで定義されているstruct)のtypealiasとして作成します。
typealias ConfigViewSectionModel = SectionModel<ConfigViewSection, ConfigItem>
// ConfigViewSectionはenumとして作成し、それぞれのセクションに応じて作成します。この例では"parameter", "playType", "interval"という3つのセクションに対応しています。
enum ConfigViewSection {
// number of sections as needed ...
case parameter
case playType
case interval
}
// ConfigItemもenumとして作成
enum ConfigItem {
// parameter section
case gameMode
case tempo
case timeLimit
case tries
case counts
case lowest
case highest
case pianoVolume
case metronomevolume
// type section
case ascend
case descend
case quarterNote
case eighthNote
case dyad
// interval section
case minSecond
case second
case minThird
case third
case fourth
case dimFifth
case fifth
case minSixth
case sixth
case minSeventh
case seventh
case octave
}
ViewControllerでは以下のように設定
class ConfigViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView()
// カスタムTableViewCellはいくつでもRegister可能 (Identifierで管理)
tableView.register(ConfigParameterTVCell.self, forCellReuseIdentifier: ConfigParameterTVCell.identifier)
tableView.register(ConfigSwitchTVCell.self, forCellReuseIdentifier: ConfigSwitchTVCell.identifier)
// セパレーターを消したい場合は.clearを指定
tableView.separatorColor = UIColor.clear
// AutoLayoutのためこのパラメータをfalseにする
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()
lazy var datasource = RxTableViewSectionedReloadDataSource<ConfigViewSectionModel>(configureCell: configureCell)
lazy var configureCell: RxTableViewSectionedReloadDataSource<ConfigViewSectionModel>.ConfigureCell = { [weak self] (dataSource, tableView, indexPath, _) in
// indexPathによりdataSourceからitem (enum型のConfigItem)をゲットする
let item = dataSource[indexPath]
// itemをswitchする
switch item {
case .tempo:
// まず、事前にregisterしてあるCustomTableViewCell (この場合はConfigParameterTVCell) をdequeueする
let cell = tableView.dequeueReusableCell(withIdentifier: ConfigParameterTVCell.identifier, for: indexPath) as! ConfigParameterTVCell
// その後、cellの各パラメータに対して処理を記載
cell.label.text = "something something"
return cell
case .timeLimit:
// 同様にcellをdequeueし処理する
// 以下省略
}
}
RxSwiftのSubject (この場合はBehaviorRelay)とのDataBindingは以下のようにします。
private func setupViewModel() {
configItems.asObservable()
.bind(to: tableView.rx.items(dataSource: datasource))
.disposed(by: bag)
}
上記のconfigItemsは以下のように定義し、設定します。
// configItemsは[ConfigViewSectionModel]のBehaviorRelayで、初期値は空の配列
let configItems = BehaviorRelay<[ConfigViewSectionModel]>(value: [])
// 3つのセクションに応じてそれぞれConfigViewSectionModelを作成します。
func updateConfigItems() {
let sections: [ConfigViewSectionModel] = [
parameterSection(),
playTypeSection(),
intervalSection(),
]
// configItemsに[ConfigViewSectionModel]を渡します
configItems.accept(sections)
}
// parameterSectionの実装
func parameterSection() -> ConfigViewSectionModel {
let items: [ConfigItem] = [
.gameMode,
.tempo,
.timeLimit,
.tries,
.counts,
.lowest,
.highest,
.pianoVolume,
.metronomevolume,
]
// このSectionModelのConstructorはRxDatasoucesで定義されている
return ConfigViewSectionModel(model: .parameter, items: items)
}
// playTypeSectionの実装
func playTypeSection() -> ConfigViewSectionModel {
let items: [ConfigItem] = [
.ascend,
.descend,
.quarterNote,
.eighthNote,
.dyad,
]
// このSectionModelのConstructorはRxDatasoucesで定義されている
return ConfigViewSectionModel(model: .playType, items: items)
}
// intervalSectionの実装
func intervalSection() -> ConfigViewSectionModel {
let items: [ConfigItem] = [
.minSecond,
.second,
.minThird,
.third,
.fourth,
.dimFifth,
.fifth,
.minSixth,
.sixth,
.minSeventh,
.seventh,
.octave,
]
// このSectionModelのConstructorはRxDatasoucesで定義されている
return ConfigViewSectionModel(model: .interval, items: items)
}