再帰処理を理解しよう！~メソッドで再帰処理を行う！~

# はじめに
自身を定義したメソッドで自身を利用することができるのはなぜだろう？:thinking:
と疑問に思いました！
再帰処理を理解することで疑問を解消することができました！

# 再帰処理とは
**「自身を定義する際に自身を利用する処理のこと」**
再帰処理の例を見てみましょう！Playgroundで動かしてみてください！
```Swift: Recursive.playground
func f1(num: Int) {
    if num != 0 {
        print("numは現在「\(num)」です。")
        f1(num: num-1)
    } else {
        print("完了")
    }
}

f1(num: 5)
```
上記のコードは自身を定義したメソッドf1で自身を利用しています！
numが0でなけらば、`print("numは現在「\(num)」です。") ` が実行され、
numが0ならば、`print("完了") `が実行されます！
上記のコードで実行されるプリント文はどうなるでしょうか？

**答えは...**
```
numは現在「5」です。
numは現在「4」です。
numは現在「3」です。
numは現在「2」です。
numは現在「1」です。
完了
```
numが0になるまで、` f1(num: num-1) `が呼び出され、実行するたびにnumが-1され続けます！

# 再帰処理のサンプルアプリ
```Swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBAction func tappedButton(_ sender: UIButton) {
        showAlert()
    }
    //再帰処理
    func showAlert() {
        let alert = UIAlertController(title: "Alert表示", message: "Alertをもう一度表示しますか？", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "リトライ", style: .default) { action in
            self.showAlert()
        }

        let cancelAction = UIAlertAction(title: "キャンセル", style: .default) { action in
            print("キャンセル")
        }
        alert.addAction(okAction)
        alert.addAction(cancelAction)
        present(alert, animated: true, completion: nil)
    }
}
```
Alertを表示ボタンを押すと、アラート文が表示され、リトライボタンを押すと、再帰処理が行われ、もう一度アラート文が表示されます！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090887/bb886ab5-02bb-340b-b7e3-dcd62ef2cbe0.png" width=300>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090887/c516c812-38c9-5de5-54a9-6c084ca9526f.png" width=300>

# 再帰処理の実用例
```Swift:TokushimaViewController.swift
class TokyoViewController: UIViewController {
    private let latitude = "35.689753"
    private let longitude = "139.691731"
    let apiClient = APIClient()
    let alertMaker = AlertMaker()
    
    @IBOutlet weak var weatherLabel: UILabel!
    @IBOutlet weak var prefectureLabel: UILabel!

    @IBAction func tappedTokyo(_ sender: UIButton) {
        showWetherView()
    }

    func showWetherView() {
        apiClient.getWeatherFromAPI(
            latitude: latitude,
            longitude: longitude,
            success: { description, cityName in
                DispatchQueue.main.async {
                    self.weatherLabel.text = description
                    self.prefectureLabel.text = cityName
                }
            },
            failure: {
                DispatchQueue.main.async {
                    let alert = self.alertMaker.showAPIErrorAlert {
                    //🟥再帰処理
                        self.showWetherView()
                    }
                    self.present(alert, animated: true, completion: nil)
                }
            }
        )
    }
}
```
API通信の結果、通信環境が悪い際には、Alert文が呼ばれ、リトライボタンを押すと、showWetherViewメソッドが再帰処理され、API通信を再度行います！
通信環境が悪い状態でリトライボタンが押され続けると、アラート文が表示され続け、
通信環境が良い状態でリトライボタンが押されると、API通信が実行され、天気と都道府県が表示されます！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090887/750314d5-2603-c88d-cc6e-17261278c363.png" width=300>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090887/b3f228b9-c59d-f6b6-da6a-80baacdac448.png" width=300>

# 参考文献

https://qiita.com/tocoteron/items/5302db69d1c9f6050b24