【Swift】BMI測定アプリで学ぶButtonでの画面遷移時の値の受け渡し方（segue）


先日、BMIを測定するシンプルなアプリケーションを作成しましたが、それは１つのViewControllerで完結するものでした。
なんとかボタンで画面遷移させ、その時に計算した値を受け渡しできないものかと考え、学んだことをこの記事にまとめていきたいと思います。


## 今回作るアプリ
身長と体重を入力するtextFieldと、それらを計算し画面遷移するbuttonを配置します。
身長と体重を入力して、buttonを押すとtextFieldに入力された値を計算し、次のviewControllerに値を受け渡します。


### 画像イメージ
簡易的に作ったレイアウトなので、ぐちゃぐちゃです。すいません＞＜


![BmiAppPreview.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181811/aabcef14-ff49-8358-e7eb-c7a1aefdcb15.png)


## 動作環境
- macOS : Big Sur 11.2.3
- Swift : 5.4
- iOS   : 14.4
- Xcode : 12.5

## 今回書く内容
- segueのidentifierを設定し、遷移先のviewControllerを取得する方法
- ２つのtextFieldの値を計算する方法
- 計算をした値を遷移先に反映させる方法
- 遷移先のViewControllerの値の受け取り方

## segueのidentifierを設定し、遷移先のviewControllerを取得する方法

### segueのidentifierを設定

main.storyboardでsegueを選択するとStoryboard Segueが設定できます
そして、segueのidentifierを設定します
今回は、identifierを”toCalculationViewController”としました

![スクリーンショット 2021-05-14 18.17.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181811/2844e48c-c739-18e1-a73f-32c9b1d3c7fc.png)

### 遷移先のviewControllerを取得する

まず遷移元のViewControllerで、特定のsegueのみに遷移先のViewControllerを取得させます


```swift:ViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // segueのIDを確認して特定のsegueのときのみ動作させる
        if segue.identifier == "toCalculationViewController"{
            
            // 遷移先のViewControllerを取得
            let next = segue.destination as? calculationViewController
}
```

## ２つのtextFieldの値を計算する方法

BMIの計算方法
![BMI図.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181811/d1e31bbc-872d-2b8c-2aa8-d70f6f87ef2d.png)
を関数にしたものがこちらです

```swift:ViewController
 //計算式の関数
    func formulation(height: Double, weight: Double) -> String {
        
    //BMIの計算方法
    let calcH = height / 100
    let calcW = weight
    var result = calcW / (calcH * calcH)
    result = floor(result * 10) / 10
    return result.description
    
    }
```

## 計算をした値を遷移先に反映させる方法

上記で説明した部分はコメントとしています

遷移先を取得したViewControllerに、BMIの計算関数（formulation関数）を加えます
その際に、テキストフィールドの型を指定します

```swift:ViewController
  //override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

      //if segue.identifier == "toCalculationViewController"{

          //let next = segue.destination as? calculationViewController


            //テキストフィールドの型を指定する
            let heightValue = Double(heightTextField.text!)
            let weightValue = Double(weightTextField.text!)
            
            //遷移先のViewControllerに計算結果を反映させる
            next?.resultValue = formulation(height: Double(heightValue!), weight: Double(weightValue!))
        }
            
    }
```

## 遷移先のViewControllerの値の受け取り方

まず、値を受け取るための変数を指定します
そして、viewDidLoadに受け取った値をラベルに表示するためのコードを書きます

```swift:calculationViewController
 //遷移先に渡したい値を格納する変数を用意する
    var resultValue : String?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //受けた値をラベルに表示する
        resultLabel.text = resultValue
        
      
        }
```

## 実装手順

### 遷移元のviewControllerの実装

```swift:ViewController
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var heightTextField: UITextField!
    
    @IBOutlet weak var weightTextField: UITextField!
    
 
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 2つのテキストフィールドの中にサーポート文字を表示させる
        heightTextField.placeholder = "身長を入力してください"
        weightTextField.placeholder = "体重を入力してください"
        
    }
    // segueが動作することをViewControllerに通知するメソッド
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // segueのIDを確認して特定のsegueのときのみ動作させる
        if segue.identifier == "toCalculationViewController"{
            
            // 遷移先のViewControllerを取得
            let next = segue.destination as? calculationViewController
            
            //テキストフィールドの型を指定する
            let heightValue = Double(heightTextField.text!)
            let weightValue = Double(weightTextField.text!)
            
            //遷移先のViewControllerに計算結果を反映させる
            next?.resultValue = formulation(height: Double(heightValue!), weight: Double(weightValue!))
        }
            
    }

    @IBAction func calculationButton(_ sender: Any) {
        //ボタンで画面を遷移させる
        performSegue(withIdentifier: "toCalculationViewController", sender: nil)
        
        }
  
    //計算式の関数
    func formulation(height: Double, weight: Double) -> String {
        
    //BMIの計算方法
    let calcH = height / 100
    let calcW = weight
    var result = calcW / (calcH * calcH)
    result = floor(result * 10) / 10
    return result.description
    
    }
   
}
```


### 遷移先のcalculationViewControllerの実装

```swift:calculationViewController
import UIKit

class calculationViewController: UIViewController {

    @IBOutlet weak var resultLabel: UILabel!
    
    //遷移先に渡したい値を格納する変数を用意する
    var resultValue : String?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //受けた値をラベルに表示する
        resultLabel.text = resultValue
       
        }
 
}
```

## まとめ

遷移先のViewControllerの取得方法はさまざまあるようですが、今回はsegueを使った方法を実践してみました
prepareメソットで、遷移先のVIewControllerに計算結果を反映させるために試行を繰り返しましたが、
formulation関数においてheightのテキストフィールドとweightのテキストフィールドにDouble型に指定し、
prepareメソットでもheightValueとweightValueにDouble型を指定してあげることで成功しました



## 参考
[【Swift】画面遷移時の値・処理の受け渡し方法（俯瞰用）](https://qiita.com/ichikawa7ss/items/df8cd87e66ada42cb560#実装手順)
[【Swift/Xcode超入門】BMIを計算するアプリを作ってみよう！](https://satoriku.com/app-dev-stepbmi/)