【Swift】CollectionViewを使用してみる

# はじめに
最近Swiftの学習をはじめました。学習の一環としてちょっとしたものを開発しています。
開発にあたり、CollectionViewを初めて使用したのでこちらについて学んだことをまとめていきます。

# 開発環境
- macOS Catalina version10.15.7
- Xcode version12.2
- Swift5

# そもそもCollectionViewとは？
CollectionViewとは、下記画像のように多くのアイテムをパネルのように一覧として表示させたい時に使われるものです。

※参考画像
<img width="50%" alt="スクリーンショット 2021-01-12 23.24.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/489eeb9a-85bf-cbe5-7453-746f74cceb01.png">

# 実際に使ってみよう
### まずはCollectionViewを設置する
![スクリーンショット 2021-01-12 23.11.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/094ea8d5-ee14-8943-0aeb-d99bc3d7ba9b.png)

設置した後は、セルのIdentifierの設定をする。
今回は、cellとする。
![スクリーンショット 2021-01-12 23.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/763ab859-082f-cc8e-2644-e4f261d173d7.png)

---

### UILabelの設置
セル上にLabelを設置します。設置した後にLabelのTagを設定する。Tagを設定することで各セルのUI部品にアクセスできるようになります。
![スクリーンショット 2021-01-12 23.40.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/9f3a64d2-a75a-871f-b83e-69bed539bc8f.png)

---

### UICollectionViewDelegateとUICollectionViewDataSourceを追加する
CollectionViewを使用するにあたり、`UICollectionViewDelegate`と`UICollectionViewDataSource`を追加する。

また追加した際に、実装する必要のあるメソッドを追加します。（Fixを押すと補完してくれます）
![スクリーンショット 2021-01-13 21.29.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/1f816f63-130c-85f7-d9a0-22e75dd9d72f.png)

```swift
//セクションの中のセルの数を返す
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
    //今回はとりあえず12とする。（配列に表示させたいデータを入れている場合は配列のデータ数を返せば良い。）
    return 12
}
```

```swift
//セルに表示する内容を記載する
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
    //storyboard上のセルを生成　storyboardのIdentifierで付けたものをここで設定する
    let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        
    //セル上のTag(1)とつけたUILabelを生成
    let label = cell.contentView.viewWithTag(1) as! UILabel
        
    //今回は簡易的にセルの番号をラベルのテキストに反映させる
    label.text = String(indexPath.row + 1)
        
    return cell
}
```

---

### ViewControllerとCollectionViewを紐付けする
storyboardのviewControllerの階層が表示されている部分で、CollectionViewを右クリックしながらViewControllerに`dataSource`と`delegate`を紐付けする。
※これを忘れるとセルは表示されないので注意！

![スクリーンショット 2021-01-13 21.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/e1e28876-8664-7e90-acce-66af9dd4fd90.png)

ここまでで下記画像のように最低限セルが表示されます。
（セルの背景色を変更することでわかりやすく確認できます。また、ラベルの位置を調整しないとセル上にうまく表示されません）

<img width="50%" alt="スクリーンショット 2021-01-12 23.24.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/5b0b6779-9ce0-95a0-a847-ac2c0b50f84f.png">


ビルドする際に、自分は以下のエラーにひっかかり少し苦戦しました。

```
Could not cast value of type 'UIView' to 'UILabel'
```

原因を調べてみたところ、どうやらTagをつける箇所を間違えていました。上記の通りLabelにTagを設定できていれば大丈夫ですが、間違えてContentView部分にTagを設定してしまったためこちらのエラーが出たのかなと思います。
Tagを設定する際は、しっかりと確認してから設定しましょう。


# セルのサイズを変更したい！
今のままではセルのサイズが小さいのでサイズを変更したい！
そんなときは、`UICollectionViewDelegateFlowLayout`を使用することでセルを調整（セルのサイズ調整、セル間の距離調整）できます。

![スクリーンショット 2021-01-13 22.22.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/e2829681-2c19-fd5d-7d59-8dc3670c254d.png)

セルのサイズを指定する処理はこちらのメソッドを使用する。

```swift
//セルのサイズを指定する処理
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
    // 横方向のスペース調整
    let horizontalSpace:CGFloat = 5

    //セルのサイズを指定。画面上にセルを3つ表示させたいのであれば、デバイスの横幅を3分割した横幅　- セル間のスペース*2（セル間のスペースが二つあるため）
    let cellSize:CGFloat = self.view.bounds.width/3 - horizontalSpace*2
        
    // 正方形で返すためにwidth,heightを同じにする
    return CGSize(width: cellSize, height: cellSize)
}
```

<img width="50%" alt="スクリーンショット 2021-01-12 23.24.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/23f828ba-0922-1609-0169-dea0f08f9207.png">


一行にセルを2つ表示させたい場合は、下記のように変えるとできます。
（行間の数が1つになる点注意）

```swift
et cellSize:CGFloat = self.view.bounds.width/2 - horizontalSpace
```


# セルをタップした際に、画面遷移させたい！
そんな時は、`didSelectItemAt`メソッドを使用することで実装できます。
（遷移先のViewControllerにセグエをつなげている前提）


```swift
//セル選択時の処理
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    //指定の遷移先に遷移する（最低限の処理）　    
    performSegue(withIdentifier: "指定のIdentifier", sender: nil)
}
```


# まとめ
今回はCollectionViewを初めて使用したので、簡単にまとめてみました。
正直まだしっかりと理解はできていないので、引き続き学習を進めていきます！

Swiftの勉強をするようになり、普段使っているアプリはどうやって作られているか意識するようになりとても勉強になります。いつか、開発したアプリをAppStoreに公開して他の人に使ってもらえるよう引き続き手を動かしていろいろ作ってみます。

以上。