デフォルトTableViewサンプル集(swift)

# はじめに
TableViewを使うときは毎回セルとかヘッダー・フッターのカスタムクラス作ったりしてたけどデフォルトのやつでも色々できるやん？ってことで色々作ってみました。

[サンプル集](https://github.com/adventam10/TableSample)

| Cell Style | AccessoryType | Color Cell | Selected Color |
| --- | --- | --- | --- |
| ![cell_style](https://user-images.githubusercontent.com/34936885/77146220-e6213f80-6acd-11ea-8c17-d0f6aab8c353.png) | ![accessory](https://user-images.githubusercontent.com/34936885/77324781-9d31eb00-6d5a-11ea-9871-773cca1adb85.png) | ![color_cell](https://user-images.githubusercontent.com/34936885/77146520-90996280-6ace-11ea-9555-31437d8e5aa6.png) | ![selected_color_cell](https://user-images.githubusercontent.com/34936885/77146446-6051c400-6ace-11ea-9cc6-1138112b8ee8.png) |

| Separator Style | Table Style | Grouped Detail | Color Section |
| --- | --- | --- | --- |
| ![separator_style](https://user-images.githubusercontent.com/34936885/77146464-69db2c00-6ace-11ea-860f-1952201852d2.png) | ![table_style](https://user-images.githubusercontent.com/34936885/77146480-7a8ba200-6ace-11ea-9124-4a306b23444d.png) | ![grouped_detail](https://user-images.githubusercontent.com/34936885/77146496-84ada080-6ace-11ea-83ac-2b65dfd31219.png) | ![color_section](https://user-images.githubusercontent.com/34936885/77158295-63f14500-6ae6-11ea-9d47-f03187baff34.png) |

# TableViewControllerを使うか否か
画面にtableViewしか表示しないって場合は基本的には `UITableViewController` を使う方が便利なのでできるだけ `UITableViewController` を使います。

便利機能

*  tableViewのひも付けとかしなくてもいい
*  var clearsSelectionOnViewWillAppear: Bool
*  var refreshControl: UIRefreshControl?
*  編集モードの時に `func setEditing(_ editing: Bool, animated: Bool)` オーバーライドしなくてもいい
*  キーボード表示時に自動でスクロールしてくれる
*  static cell が使える
*  セーフエリアまわりもなんかいい感じにしてくれる

[UITableViewControllerドキュメント](https://developer.apple.com/documentation/uikit/uitableviewcontroller)

# Cell Style
`UITableViewCell` には下記の `Style` があります。

* default (Basic)
* value1 (Right Detail)
* value2 (Left Detail)
* subtitle (Subtitle)

こんな感じ。

<img width="300" alt="cell_style" src="https://user-images.githubusercontent.com/34936885/77146220-e6213f80-6acd-11ea-8c17-d0f6aab8c353.png">

default (Basic) 以外は detail テキストも設定できる。value2 (Left Detail) 以外は image も設定できる。

下記のように設定

```swift
cell.textLabel?.text = "title"
cell.detailTextLabel?.text = "detail"
cell.imageView?.image = UIImage(named: "sample")
```

# Cell AccessoryType
`UITableViewCell` には下記の `AccessoryType` があります。

* none
* disclosureIndicator
* detailDisclosureButton
* checkmark
* detailButton

こんな感じ。

<img width="300" alt="accessoryType" src="https://user-images.githubusercontent.com/34936885/77324781-9d31eb00-6d5a-11ea-9871-773cca1adb85.png">

下記のように設定（もしくは Storyboard で設定）

```swift
cell.accessoryType = .none
cell.tintColor = .red // 色設定（disclosureIndicatorは変わらない）
```

# Cell 背景色
`UITableViewCell` の背景色を設定する。

こんな感じ。

<img width="300" alt="cell_color" src="https://user-images.githubusercontent.com/34936885/77146520-90996280-6ace-11ea-9555-31437d8e5aa6.png">

下記のように設定

```swift
if cell.backgroundView == nil {
  cell.backgroundView = UIView()
}
cell.backgroundView?.backgroundColor = .red
```

上記のように `backgroundView` を設定する。確か `cell.backgroundColor = .red` はダメだった気がするけど動いた（勝手にいい感じにしてくれるのかも？？）

# Cell 選択時の背景色
`UITableViewCell` の選択時の背景色を設定する。

こんな感じ。

<img width="300" alt="cell_selected_color" src="https://user-images.githubusercontent.com/34936885/77146446-6051c400-6ace-11ea-9cc6-1138112b8ee8.png">

下記のように設定

```swift
let v = UIView()
v.backgroundColor = .red
cell.selectedBackgroundView = v
```

選択時の背景色の設定はよくわからない...

`cell.selectedBackgroundView?.backgroundColor = .red` ではダメだった:scream:

リファレンスに下記のように書いてあるが別に `nil` でもなかった...
> Default is nil for cells in UITableViewStylePlain, and non-nil for UITableViewStyleGrouped. 

# Separator
## Style
`UITableView` には下記の `SeparatorStyle` があります。

* none
* singleLine (Default)
* singleLineEtched (deprecated)

こんな感じ。

<img width="300" alt="separator" src="https://user-images.githubusercontent.com/34936885/77146464-69db2c00-6ace-11ea-860f-1952201852d2.png">

Storyboard で設定する場合は Default も含めて4パターンあるが Default は `singleLine` なので変わらない。また、`singleLineEtched` は Deprecated になっておりこちらも `singleLine` 同様の見た目になった。（`tableView` のスタイルを `Grouped` にしても変化なし）

なので `SeparatorStyle` は下記の２パターンのみ

* none
* singleLine

下記のように設定（もしくは Storyboard で設定）

```swift
tableView.separatorStyle = .none
```

## Color
区切り線も色も設定できるが、セルごとの設定は不可。

こんな感じ。

<img width="300" alt="separator_color" src="https://user-images.githubusercontent.com/34936885/77153137-99913080-6adc-11ea-946e-bb20e920f653.png">

下記のように設定（もしくは Storyboard で設定）

```swift
tableView.separatorColor = .blue
```

## Inset
区切り線の `inset` はセルごとの設定も可。

こんな感じ。

| テーブルに設定 | セルごとに設定 |
| --- | --- |
| <img width="300" alt="inset_all" src="https://user-images.githubusercontent.com/34936885/77153105-867e6080-6adc-11ea-832a-6e81730a7624.png"> | <img width="300" alt="inset_cell" src="https://user-images.githubusercontent.com/34936885/77153124-926a2280-6adc-11ea-9456-a1c7e26db5d6.png"> |

下記のように設定（もしくは Storyboard で設定）

```swift
// すべて同じ値を設定する場合
tableView.separatorInset = .zero
// セルごとに設定する場合
cell.separatorInset = .init(top: 0, left: 15 * CGFloat(indexPath.row), bottom: 0, right: 0)
```

## 小技(セルがない部分の区切り線を消す)
下記のようにするとセルがない部分の区切り線を消すことができる:v:

```swift
tableView.tableFooterView = UIView()
```

| 通常 | footer設定 |
| --- | --- |
| ![line](https://user-images.githubusercontent.com/34936885/77154489-25a45780-6adf-11ea-894a-6e42080fdfe4.png) | ![line_none](https://user-images.githubusercontent.com/34936885/77154468-1a512c00-6adf-11ea-89b4-a98cdabeaaea.png) |

# Table Style
`UITableView` には下記の `Style` があります。

* plain
* grouped
* insetGrouped

こんな感じ。(Plain とか表示してるのは TableView とは関係ないただの label です)

`instGrouped` はそのままだとわかりにくいので `tableView` の背景色を変えています。

<img width="300" alt="table_style" src="https://user-images.githubusercontent.com/34936885/77146480-7a8ba200-6ace-11ea-9124-4a306b23444d.png">

ぱっと見わかりにくいですが下記のようにヘッダー・フッターを設定すると違いがわかります。

```swift
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  return "section header \(section)"
}

func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
  return "section footer \(section)"
}
```

`plain` の場合スクロールしてもヘッダー部分は固定される。

<img width="300" alt="plain" src="https://user-images.githubusercontent.com/34936885/77153497-2f2cc000-6add-11ea-9a76-c38d2f99b8ed.png">

`grouped` と `insetGrouped` の場合スクロールするとヘッダー部分も一緒にスクロールされる。ヘッダーの文字はすべて大文字になる。

| grouped | insetGrouped |
| --- | --- |
| <img width="300" alt="grouped" src="https://user-images.githubusercontent.com/34936885/77153510-3653ce00-6add-11ea-8669-244f712c7614.png"> | <img width="300" alt="inset_grouped" src="https://user-images.githubusercontent.com/34936885/77153530-3fdd3600-6add-11ea-83a3-a9894dbe5574.png"> |

## 小技（ヘッダー・フッターの文字色を変える）
下記のようにするとヘッダー・フッターの文字色を設定できる:clap:

```swift
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
  (view as? UITableViewHeaderFooterView)?.textLabel?.textColor = .red
}

func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
  (view as? UITableViewHeaderFooterView)?.textLabel?.textColor = .blue
}
```

こんな感じ

<img width="300" alt="section_color" src="https://user-images.githubusercontent.com/34936885/77153545-47044400-6add-11ea-9b94-c4b0a0745259.png">

## Grouped の detailText 設定
`grouped` と `insetGrouped` の場合ヘッダー部分に `detailTextLabel` を設定できる。

> If you configured your table view with the group style, you can also configure the detailTextLabel property.

こんな感じ(ヘッダーは大文字にならない)

<img width="300" alt="grouped_detail" src="https://user-images.githubusercontent.com/34936885/77146496-84ada080-6ace-11ea-83ac-2b65dfd31219.png">

下記のように設定する。

Storyboardで Sections のところの Automatic にチェックをつける

<img width="264" alt="layout" src="https://user-images.githubusercontent.com/34936885/77146558-a7d85000-6ace-11ea-930d-1546414a38cd.png">

これをしておかないと `textLabel ` と `detailTextLabel` が重なったりする。

```swift
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  var header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header")
  if header == nil {
    header = UITableViewHeaderFooterView(reuseIdentifier: "header")
  }
  header?.textLabel?.text = "section header \(section)"
  header?.detailTextLabel?.text = "detail"
  return header
}
```

# Section Color (ヘッダー・フッター)
セクションのヘッダー・フッターの背景色を設定する。

こんな感じ

<img width="300" alt="color_section" src="https://user-images.githubusercontent.com/34936885/77158295-63f14500-6ae6-11ea-9d47-f03187baff34.png">

下記のように設定する。

```swift
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  var header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header")
  if header == nil {
    header = UITableViewHeaderFooterView(reuseIdentifier: "header")
  }
  if header?.backgroundView == nil {
    header?.backgroundView = UIView()
  }
  header?.backgroundView?.backgroundColor = .red
  return header
}

override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
  var footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: "footer")
  if footer == nil {
    footer = UITableViewHeaderFooterView(reuseIdentifier: "footer")
  }
  if footer?.backgroundView == nil {
    footer?.backgroundView = UIView()
  }
  footer?.backgroundView?.backgroundColor = .red
  return footer
}
```

# さいごに
カスタムクラスをつくらなくてもわりと色々できそう。

Table関連はよく使うけど実装方法忘れたりするのでもっと充実させたい。

プルリクくれてもええんやで:rolling_eyes:

[サンプル集](https://github.com/adventam10/TableSample)

[プルリク大歓迎（だれかきてくれないかな:eyes::eyes::eyes:）](https://github.com/adventam10/TableSample/blob/master/CONTRIBUTING.ja.md)