選択上限をつけた複数選択可能なTableViewの実装が調べても出てこなかったので、簡単に作ってみました。
今回実現したいTableView
- 複数選択可能
- 選択状態がスクロールによって他のCellにズレない
- 選択できる数に上限をつける
1. 複数選択を可能にする
MultipleTableView.swift
// tableViewのisMultipleTouchEnabledをtrueにする
isMultipleTouchEnabled = true
これだけで複数選択が可能になる。
2. 選択状態がスクロールによって他のCellにズレない
Model
に選択状態を持って、その値を元にCell
をinit
する。
(R.swift使っております)
MultipleTableView.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: R.reuseIdentifier.multipleTableViewCell.identifier,
for: indexPath) as! MultipleTableViewCell
cell.selectionStyle = .none
cell.kind = kinds[indexPath.row]
return cell
}
MultipleTableViewCell.swift
var kind: KindModel? {
didSet {
accessoryType = kind?.isSelected ?? false ? .checkmark : .none
initLabel()
}
}
選択状態のset
は次の 選択できる数に上限をつける と合わせて紹介します。
3. 選択できる数に上限をつける
選択状態に上限をつけるのは、TableView
に選択数のカウンタをつけるのが1番楽かなと思います。
もっとかっこいい方法はないかと考えたのですが、特に思いつきませんでした。。
MultipleTableView.swift
var selectedIndex: [Int] = []
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let row = selectedIndex.filter({ $0 == indexPath.row }).first {
guard let removeIndex = selectedIndex.firstIndex(of: row) else { return }
selectedIndex.remove(at: removeIndex)
kinds[indexPath.row].isSelected.toggle()
return
}
// 今回は上限を3にしました
if selectedIndex.count > 2 { return }
kinds[indexPath.row].isSelected.toggle()
selectedIndex.append(indexPath.row)
}
これで上限の管理は完了です!
didDeselectRowAt
使いたかったけど、なぜか呼ばれなかった。
SOFにも同じような投稿がありましたが、解決ならずだったので諦めました。。