【SwiftUI】Listを作成する

# 環境
Xcode 13.2.1
Swift 5.5.2

# Listとは
SwiftUIでは、これまでのUIKitのUITableViewやUICollectionViewを用いたリスト表示を実装したい場合は、`List`を使うことで再現ができます。
Listも表示が画面からはみ出た範囲をスクロールできるようになっています。
一番シンプルにListを用いた静的リストの実装は以下になります。Listも表示が画面からはみ出た範囲をスクロールできるようになっています。

```swift
var body: some View {
    List {
        Text("First Item")
        Text("Second Item")
        Text("Third Item")
    }
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/b6fc1af4-d14b-59e7-9c92-37c49254ca8e.png">

# 動的リストを作成する
動的にリストを作成した場合は以下のように実装することができます。`Identifiable`に準拠したFruitの配列からListを作成しています。
`FruitListItemView`は、Listの1つのデータを表示するためのViewです。

```swift
struct Fruit: Identifiable {
    let id = UUID()
    let name: String
}

struct FruitListItemView: View {
    var fruit: Fruit
    
    var body: some View {
        Text(fruit.name)
    }
}

struct ContentView: View {
    private var fruits = [
        Fruit(name: "Apple"),
        Fruit(name: "Orange"),
        Fruit(name: "Banana"),
        Fruit(name: "peach"),
        Fruit(name: "strawberry")
    ]

    var body: some View {
        List(fruits) {
            FruitListItemView(fruit: fruit)
        }
    }
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/b71e3745-8998-689d-69f7-31547d07179d.png">

`ForEach`を用いても同じようにリストを作成することができます。

```swift
List {
    ForEach(fruits) { fruit in
        FruitListItemView(fruit: fruit)
    }
}
```

動的と静的両方をListに含ませることもできます。このように自由なリストを作成することができるので`ForEach`の方が使う場面は多いと思います。

```swift
List {
    Text("Dog")
    Text("Cat")
    ForEach(fruits) { fruit in
        FruitListItemView(fruit: fruit)
    }
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/d318039c-3d5a-21e2-f041-6067e36aef06.png">

`Identifiable`に準拠していないデータを用いる場合は`id`を指定する必要があります。

```swift
private var fruits = [
    "Apple",
    "Orange",
    "Banana",
    "peach",
    "strawberry",
]

var body: some View {
    List {
        ForEach(fruits, id: \.self) { fruit in
            FruitListItemView(fruit: fruit)
        }
    }
}
```

# 画面遷移をさせる
リスト表示したデータから画面遷移を実装したい場合は`NavigationLink`を使用します。

```swift
NavigationView {
    List {
        ForEach(fruits) { fruit in
            NavigationLink(destination: SecondView()) {
                FruitListItemView(fruit: fruit)
            }
        }
    }
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/b6c995ba-a635-885d-93d7-1dafa9b49168.png">

:::note warn
NavigationViewの中にListを置いていないと、タップができず画面遷移がされないので注意が必要です。
:::

# 選択可能なリストにする
単一選択や複数選択ができるようにするには`selection`を設定します。

#### 単一選択
選択した値を格納するための`id`と同じ型の`State`変数をListの引数`selection`に指定します。

```swift
@State private var selectedFruit: UUID?

var body: some View {
    NavigationView {
        List(selection: $selectedFruit) {
            ForEach(fruits) { fruit in
                FruitListItemView(fruit: fruit)
            }
        }
        .navigationTitle("Fruits")
        .toolbar { EditButton() }
    }
}
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/62a86d06-75c8-40c2-61ce-710ddab5c3b7.png">

#### 複数選択
Listの引数`selection`に指定する変数を`Set`にすることで複数選択ができるようになります。

```swift
@State private var selectedFruit = Set<UUID>()
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/6aa5752a-0b05-54ed-e3ec-76ec3f314f1c.png">

# セクションを追加する
表示するViewを`Section`で囲むことでセクションを追加できます。`header`と`footer`はViewを返すのでTextである必要はありません。ヘッダーのテキストは大文字になるようです。

```swift
List {
    Section {
        ForEach(fruits) { fruit in
            FruitListItemView(fruit: fruit, selectedFruit: selectedFruit)
        }
    } header: {
        Text("Fruits")
    } footer: {
        Text("End")
    }
    
    Section {
        ForEach(animals, id: \.self) { animal in
            Text(animal)
        }
    } header: {
        Text("Animals")
    }
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/d75c53ea-aa87-a429-4f58-ddb903a50e07.png">

# Listの表示スタイルを変更する
`listStyle(_:)`モディファイアを指定することでListの見た目を変更することができます。

```swift
List {
}
.listStyle(DefaultListStyle())
```

#### 指定なし or DefaultListStyle
```swift
.listStyle(DefaultListStyle())
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/51838794-bcea-b3f4-70ec-b4d864856af4.png">

#### InsetListStyle
```swift
.listStyle(InsetListStyle())
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/963f5ea7-ca87-7a11-31f1-d192fb339aaf.png">


#### PlainListStyle
```swift
.listStyle(PlainListStyle())
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/f31d335f-ae34-3320-94a3-7a66baf1fc22.png">


#### GroupedListStyle
```swift
.listStyle(GroupedListStyle())
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/8bc2cbb3-5758-def6-66a3-7af9ac76c217.png">

#### SidebarListStyle
```swift
.listStyle(SidebarListStyle())
```
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/d26755ea-41b1-916b-2d01-98e7adc29a1b.png">