【Swift】タプル型の便利な使い方（備考録）

## 導入
Swiftを使っていて、これまでタプル型を自分で実装して使う機会がなかったんですが、
開発していたらタプル型ってこういう時に使えばいいんだという気づきがあったため記事を書きました。

僕はMVPモデルでアプリ開発をしていた時に、タプル型の利便性に気付かされたので、今回はMVPモデルで作ったサンプルアプリを元に解説します。
※あまりに簡素なサンプルアプリであり、Modelは不要なので今回は、ViewとPresenterのみを使用します。

■ MVPモデルについてはこちらの記事が大変参考になりました
https://qiita.com/hicka04/items/25be38a90fdde29c97c2

## サンプルアプリについて
下記に画面のキャプチャを載せました。
「計算ボタン」をタップすると、画面上に書かれている足し算を行い、水色の枠の部分に答えを表示します。
<img width="280" alt="TupleApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580445/be5369b2-88fd-f495-0273-e19a6eef55e1.png">
ありえないくらい簡素なサンプルアプリでございます。

## ソースコード
ちなみに、今回やろうとしている処理は`calculate()`がViewControllerから引数を受ける形にすればいいのですが、今回はタプル型を使いたいため、あえて引数を渡さないようにしています。
もっと複雑なアプリを作る場合、Presenter内の処理で、ViewControllerから引数として渡された値以外も、ViewControllerから取得して使いたいということがあると思います。
今回はそういったケースを想定しております。

MVPアーキテクチャを採用する場合、PresenterはViewが持っているLabelなどを直接参照したり、更新したりすることなく、`PresenterProtocol`で定義されたメソッドを通して、値の取得やViewへの更新依頼を行います。

今回は、`getAdditionalNumber()`を用いて、ViewControllerの値を取得しています。

#### ■タプル型を活用した場合
１つのメソッドでViewControllerの２つの値を取得することが可能です。今回は、足し算に必要な２つの数を１つのメソッドで取得できています。
あとはPresenterで使いたい値を自由に取り出すだけで、簡単に処理できます。
今回は、`calculateTuple()`を呼び出した場合の処理になります。

####■タプル型を使わない場合
逆に、タプル型を使わない場合、各ラベルを取得するのに別々のメソッドを書かないといけないので、`PresenterProtocol`に定義しないと行けないメソッドが増殖してしまいます。
そのたびにメソッドを増やさないといけないのは手間ですし、無駄なコードを書かないと行けないかなと思います。
今回は、`calculate()`を呼び出した場合の処理になります。

```swift:ViewController.swift
class ViewController: UIViewController {
    
    @IBOutlet weak var labelNum1: UILabel!
    @IBOutlet weak var labelNum2: UILabel!
    @IBOutlet weak var labelAnswer: UILabel!
    
    var presenter: Presenter?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        presenter = Presenter(self)
    }

    @IBAction func touchCalculator(_ sender: Any) {
        // タプル型を使わない場合の処理を実行
        // presenter?.calculate()
        // タプル型を使う場合の処理を実行
        presenter?.calculateTuple()
    }
}


extension ViewController: PresenterProtocol {
    func updateAnswerLabel(answer: Int) {
        labelAnswer.text = "\(answer)"
    }
    
    // タプル型を使わない場合
    func getAdditionalNumber1() -> String {
        return labelNum1.text ?? ""
    }
    func getAdditionalNumber2() -> String {
        return labelNum2.text ?? ""
    }
    
    // タプル型を使う場合
    func getAdditionalNumber() -> (num1: String, num2: String) {
        return (labelNum1.text ?? "", labelNum2.text ?? "")
    }
}
```

```swift:Presenter.swift
import Foundation

protocol PresenterProtocol: AnyObject {
    func updateAnswerLabel(answer: Int) -> Void
    
    // タプル型を使わない場合
    func getAdditionalNumber1() -> String
    func getAdditionalNumber2() -> String
    // タプル型を使う場合
    func getAdditionalNumber() -> (num1: String, num2: String)
}

class Presenter {
    
    weak var view: PresenterProtocol?
    
    init(_ view: PresenterProtocol) {
        self.view = view
    }
    
    func calculate() {
        let _num1 = view?.getAdditionalNumber1()
        let _num2 = view?.getAdditionalNumber2()
        guard let num1 = _num1, let num2 = _num2 else {
            return
        }
        let sum = Int(num1)! + Int(num2)!
        view?.updateAnswerLabel(answer: sum)
    }
    
    func calculateTuple() {
        let tuple = view?.getAdditionalNumber()
        guard let num1 = tuple?.num1, let num2 = tuple?.num2 else {
            return
        }
        let sum = Int(num1)! + Int(num2)!
        view?.updateAnswerLabel(answer: sum)
    }
}
```

##まとめ
今回は、タプル型の使い所について、自分の備考録を兼ねて書いてみました。
サンプルアプリが簡素だったため、メリットが捉えにくかったかもしれませんが、
**「似たような属性の値を複数以上（配列にするほど長くもない程度）取得したい場合に、メソッドの戻り値として使えるよ」**
ということが伝わっていればいいなと思います。。。