複数apiを叩いて全ての結果が0件だった場合のみ処理をするお話


0件の場合の表示処理について、GCD調べたんでそのまとめをしました



# 1.やりたいこと
複数のAPIの結果が0件だった場合に特定のviewを表示させたい
「複数の」って言うのが今回の大きなポイント。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/55864/277925a4-d74a-a218-0406-dad593b76f86.png)




# 2.何が難しいんでっか？
通常APIが一つの場合こんな感じでできる。

```swift
repository.apiHogeHoge1() { (result) in
            switch result {
           case .success(let response):
          
          if response.count == 0 {
            //apiが1つならここでできる
          }
}
```

しかし2つの場合こうなる

```swift
repository.apiHogeHoge1() { (result) in
            switch result {
           case .success(let response):
           
          if response.count == 0 {
            // ここに入った場合では条件不足
          }
}

repository.apiHogeHoge2() { (result) in
            switch result {
           case .success(let response):
          
          if response.count == 0 {
　　　　　　　　// ここに入った場合では条件不足
          }
}
// 言わずもがなだがここでは判定できない......

```

まぁつまり
**apiHogeHoge1()もapiHogeHoge2()も終了したら判定したいよね！！！**
ってこと
非同期処理ってやつですね。

# 3.そこでGCDです
https://developer.apple.com/documentation/dispatch/dispatchqueue

よく `DispatchQueue.main.async` って記述を見ると思います（僕だけかも...）
UI更新をしたいときはメインスレッドである必要があるので、このような記述を使いますね。

```swift
    DispatchQueue.main.async {
        // UI更新とか
    }
```

今回の場合だと
**apiHogeHoge1()もapiHogeHoge2()も終了したら判定したいよね！！！**
ってことで、キューのなかにタスクを入れて、全てのタスクがなくなったら実行するって形でやります。



こんな感じ。

```swift
        let dispatchGroup = DispatchGroup()
        //並列処理のキューを作成
        //labelに意味があるかは不明
        let dispatchQueue = DispatchQueue(label: "queue", attributes: .concurrent)



        dispatchQueue.async(group: dispatchGroup) {
            //キューに追加
            dispatchGroup.enter()
          repository.apiHogeHoge1() { (result) in
                      switch result {
                     case .success(let response):
                     
                     //結果入れとく
                     self.apiHogeHoge1Result = response
               //データが取得できたタイミングでキューから削除
               dispatchGroup.leave()
          }
        }

        dispatchQueue.async(group: dispatchGroup) {
            //キューに追加
            dispatchGroup.enter()
          repository.apiHogeHoge2() { (result) in
                      switch result {
                     case .success(let response):
                     
                     //結果入れとく
                     self.apiHogeHoge2Result = response
               //データが取得できたタイミングでキューから削除
               dispatchGroup.leave()
          }
        }
       }

       dispatchGroup.notify(queue: .main) {
       
              if self.apiHogeHoge1Result.count == 0 && self.apiHogeHoge2Result.count == 0 {
                  //どっちも0件なら0件用のviewを追加する
                  self.scrollview.addSubview(self.noEventView)
              }
       }

```

# 4.まとめ
キューがわかってれば、すんなり受け入れられるはず。
非同期処理はアプリ開発で欠かせないところなので使える違和感なく使える状態が望ましい。
これ以外にも「何を？」「どのタイミングで？」「実行する？」っていつも考えてる気がする

#参考サイト
[Swift 3] Swift 3時代のGCDの基本的な使い方https://dev.classmethod.jp/smartphone/iphone/swift-3-how-to-use-gcd-api-1/
Swift 3における非同期処理
https://1000ch.net/posts/2016/dispatch-queue.html
非同期通信で、ある処理のあとに別の非同期通信を行いたい。
https://teratail.com/questions/72250
Concurrent Programming With GCD in Swift 3
https://developer.apple.com/videos/play/wwdc2016/720/