Swiftで簡単なアプリ作ってみたよって話

# はじめに

swiftのstoryboardを使って四則演算の問題を出題するアプリを作ってみました。
勉強のために1時間程度で簡単につくってみたものですが、とりあえず動くものになったので確認の意味を込めてアウトプット

# UI構成とアプリ概要
![swift-math.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1193085/0522d728-196e-8d79-644d-12823295b2e9.png)

- 左のページ
    - ホームのページ
    - 「START」ボタンを押すと、中央のページへ遷移する
- 中央のページ
    - 四則演算の問題が出題されるページ
    - 10問答えると右のページへ遷移する
- 右のページ
    - 問題の正答率を表示するページ
    - 「BACK」ボタンを押すと左のページへ遷移する

# コントローラの処理
## 左のページの処理

``` ViewContoroller.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    @IBAction func backToTitle(sender: UIStoryboardSegue) {
        
    }

}
```

特に説明することはなし。Storyboardからボタン押下時に中央のページへ遷移するよう設定した。

``` swift
@IBAction func backToTitle(sender: UIStoryboardSegue) {
        
    }
```
この部分に関しては、右のページの「BACK」ボタンを押した際にこのページに戻るようにしたいため記載。
storyboard上でこの関数を設定することで処理が動く。

## 中央のページ
``` QuizViewController.swift
import UIKit

class QuizViewController: UIViewController {
    
    let total = 10 // 問題数
    var correct = 0 // 正解数
    var questionIndex = 0 // 現在出題した数
    var answerIndex = 0 // どのボタンが押下されたかを記載 (1:+, 2:-, 3:×,4:÷)
    
    @IBOutlet var leftNumberLabel: UILabel!
    @IBOutlet var centerNumberLabel: UILabel!
    @IBOutlet var rightNumberLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        setQuestions()

        // Do any additional setup after loading the view.
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let resultVC = segue.destination as? ResultViewController {
            resultVC.result = Double(correct) / Double(total) * 100.0
        }
    }
    
    @IBAction func tapped(sender: UIButton) {
        if sender.tag - 1 == answerIndex {
            correct += 1
        }
        
        questionIndex += 1
        if questionIndex >= total {
            performSegue(withIdentifier: "QuizToResult", sender: nil)
        } else {
            setQuestions()
        }
    }
    
    func setQuestions() {
        let leftNum = Int(arc4random_uniform(10))
        var centerNum = Int(arc4random_uniform(10))
        
        answerIndex = Int(arc4random_uniform(4))
        
        switch answerIndex {
        case 0:
            rightNumberLabel.text = "\(leftNum + centerNum)"
        case 1:
            rightNumberLabel.text = "\(leftNum - centerNum)"
        case 2:
            rightNumberLabel.text = "\(leftNum * centerNum)"
        default:
            if centerNum == 0 {
                centerNum = 1
            }
            rightNumberLabel.text = "\(leftNum / centerNum)"
        }
        
        leftNumberLabel.text = "\(leftNum)"
        centerNumberLabel.text = "\(centerNum)"
    }
}

```

以下、それぞれの処理について簡単に説明する

``` swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let resultVC = segue.destination as? ResultViewController {
            resultVC.result = Double(correct) / Double(total) * 100.0
        }
    }
```

上のメソッドは後で記載するResultController.swfit(右の画面のコントローラの動きを記載したもの)に値を受け渡す役割をしている。

``` swift
@IBAction func tapped(sender: UIButton) {
        if sender.tag - 1 == answerIndex {
            correct += 1
        }
        
        questionIndex += 1
        if questionIndex >= total {
            performSegue(withIdentifier: "QuizToResult", sender: nil)
        } else {
            setQuestions()
        }
    }
```

このメソッドは「+」、「-」、「×」、「÷」ボタンを押した際に正解かどうかの判定を行っている。
この際に、出題数に1足す処理と10問出題したかどうかを判定し、10問出題しているなら、右のページへ、そうでないなら再び問題を出す処理を行っている。

``` swift
func setQuestions() {
        let leftNum = Int(arc4random_uniform(10))
        var centerNum = Int(arc4random_uniform(10))
        
        answerIndex = Int(arc4random_uniform(4))
        
        switch answerIndex {
        case 0:
            rightNumberLabel.text = "\(leftNum + centerNum)"
        case 1:
            rightNumberLabel.text = "\(leftNum - centerNum)"
        case 2:
            rightNumberLabel.text = "\(leftNum * centerNum)"
        default:
            if centerNum == 0 {
                centerNum = 1
            }
            rightNumberLabel.text = "\(leftNum / centerNum)"
        }
        
        leftNumberLabel.text = "\(leftNum)"
        centerNumberLabel.text = "\(centerNum)"
    }
```

このメソッドは問題を出す処理を行っている。
まず
``` swift
Int(arc4random_uniform(10))
```
で、0~9までのランダムな数を一つ選び、leftNum, centerNumに代入、answerNumには0~4までのランダムな数を選んでいる。
ここの0~4はそれぞれ「+」、「-」、「×」、「÷」のボタンに対応させている。(ボタンのindexはstoryboard上で設定)

answerNumの値によってなんの計算を行っているのかを判定しているため、rightNumLabel(計算の答えとなる場所)にはswitch文で分岐させている。

## 右のページ
``` ResultController.swift
import UIKit

class ResultViewController: UIViewController {
    
    var result = 0.0
    
    @IBOutlet var resultLabel: UILabel!
    @IBOutlet var messageLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        resultLabel.text = "\(round(result))%"
        if result < 50 {
            messageLabel.text = "PLEASE TRY AGAIN!"
        } else if result < 80 {
            messageLabel.text = "NICE!"
        } else {
            messageLabel.text = "YOU ARE GREAT!"
        }
    }
}
```

このクラスでは問題の正答率から、表示する%と、テキストを変更する処理を行っている。

# 実際の例
![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1193085/91c19287-6864-3660-3d68-ae929b398997.png)

![test2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1193085/e49ec5c0-b876-27fa-bc0c-2c35f7ce014e.png)

実際に動かしてみるとこんな感じ。
1枚目の画像のように問題を解いていき、10問解き終わると、正答率を表示してくれるアプリができた。

# さいごに
今回はstoryboardを使ったとても簡単なアプリを作ってみました。
このレベルのアプリなら1時間くらいでちょちょいとできるswiftってすげー

# 参考文献

https://www.udemy.com/course/ios-apps/