【Swift5/Xcode】入門編!クイズアプリを作成してみよう!参考書より丁寧に解説します。【Part4】

サトリク

この記事は、Pert4です。前編を読んでいない方は、上記の記事から読んでください。

今の状態

  • スタートボタンを押すと、1問目が表示される
  • ボタンを押すと、コンソールに番号が表示される

サトリク

今回の講座では一気にクイズアプリらしくなります!コーディングが多いので、注意しながらやっていきましょう!

 

 

ボタンを押したときに正誤判定を行う

ボタンを押したときに、正解か不正解かをコンソールに出したいと思います。

STEP.1
QuizViewControllerを開く

左側のメニューから、QuizViewController.swiftをダブルクリックする

STEP.2
ボタンを押したときの正誤判定

ボタンを押したときに呼ばれるメソッドが38行目あたりにあります。

この中に、問題データの正解番号とPert2でつけたtagを比較して正誤判定をしていきます。

@IBAction func btnAction(sender: UIButton) {
    //ボタンを押したときに呼ばれる
    print(sender.tag)
}

 

以下のように書き換えてください。

@IBAction func btnAction(sender: UIButton) {
    if sender.tag == Int(quizArray[1]) {
        print("正解")
    } else {
        print("不正解")
    }
}

 

もし(if)押されたボタン(sender.tag)が正解番号(Int(quizArray[1]))と同じ(==)だったら正解と表示(print("正解"))し、そうでなかったら(else) 不正解と表示(print("不正解"))する

というプログラムです。

STEP.3
実行して確認

左上のボタンを押すか、command + rで実行しましょう。

正解のボタンを押すと、コンソールに正解と表示され、不正解のボタンを押すと不正解と表示されるはずです。

完了
上記の確認ができたら、正誤判定は完了です。

次の問題を表示する

次はボタンを押したら、次の問題を表示するプログラムを記述していきたいと思います。

記述するファイルは、QuizVireControllerです。

STEP.1
次の問題を表示するプログラム

46行目あたり(先ほど記述した、ボタンの正誤判定の下)に以下のコード(メソッド)記述していきます。

func nextQuiz() {
    quizCount += 1
    quizArray.removeAll()
    quizArray = csvArray[quizCount].components(separatedBy: ",")
    quizNumberLabel.text = "第\(quizCount + 1)問"
    quizTextView.text = quizArray[0]
    answerBtn1.setTitle(quizArray[2], for: .normal)
    answerBtn2.setTitle(quizArray[3], for: .normal)
    answerBtn3.setTitle(quizArray[4], for: .normal)
    answerBtn4.setTitle(quizArray[5], for: .normal)
}

 

簡単に解説

quizCount += 1:quizCountに+1します。次の記述と同じことをしています。quizCount = quizCount + 1

quizArray = csvArray[quizCount].components(separatedBy: ","):csvArrayから問題を取り出す

それ以降:問題をセットする

STEP.2
メソッドを呼ぶ

先ほど書いたメソッドを、ボタンを押したときに実行されるようにしたいので、

38行目あたりのボタンを押したときの処理を以下のようにnextQuiz()を書きたします。

@IBAction func btnAction(sender: UIButton) {
    if sender.tag == Int(quizArray[1]) {
        print("正解")
    } else {
        print("不正解")
    }
    nextQuiz()
}

 

STEP.3
実行して確認

左上のボタンを押すか、command + rで実行しましょう。

ボタンを押すと、次の問題がセットされると思います。

がしかし、ここで見つかった問題が2点

  1. Labelの幅が狭すぎて文字が…になる
  2. 5問以上行うと、アプリが強制終了してしまう。

完了

ボタンを押すと、次の問題がセットされることを確認できたら完了です。

 

オブジェクトの幅を広げる

先ほど実行して見つかった、Labelの幅が狭すぎて文字が…になる問題を解決しましょう。

STEP.1
Main.storyboardを開く

(show the Project navigator)を選択

②Main.storyboardを選択

STEP.2
Labelの幅を広げる

①Labelを横いっぱいに広げましょう。

②Alignmentを中央揃えにしましょう。

STEP.3
Buttonの幅を広げる

同じくButtonの幅も横いっぱいに広げましょう。

STEP.4
実行して確認

左上のボタンを押すか、command + rで実行して問題数や、選択肢が…にならないことを確認してください。

完了

うまく表示できていたら完了です。

5問終わったらスコア画面に遷移させる

今の段階では、5問目が終わると6問目がないためアプリが強制終了してしまいます。

5問終わると、スコア画面に遷移するようにしましょう。

STEP.1
Main.storyboardを開く

Main.storyboardを開きます。

STEP.2
画面遷移させる

Part2でスタートボタンを押したら、画面遷移するという処理を行いました。

その時は、スタートボタンからcontrolを押しながら問題画面にドラッグ&ドロップしました。

ですが、今回は四つのボタンどのボタンを押しても5問目だったら、画面遷移させるという処理によって画面遷移するかしないかを決めます。

そのような場合は、以下のように接続します。

問題画面のバーの左側の controlを押しながら、スコア画面にドラッグ&ドロップ

左のようなウィンドウが表示されるので、「Present Modally」を選択

そうすると、Segueができます。

STEP.3
SegueにIDをつける

①Segueを選択

② (Show the Attributes inspector)を選択する

③Idenrifierにscoreと入力する

SegueにIDをつけることができました。

STEP.4
スコア画面をフルスクリーンにする

①スコア画面の  を選択

② (Show the Attributes inspector)を選択する

③PresentationをFull Screenにする

STEP.5
QuizViewControllerを開く

左のメニューからQuizViewController.swiftをダブルクリックします。

STEP.6
問題数を入れる変数を用意

問題数を入れる変数を用意します。

23行目あたり(var quizCount = 0の下)に以下のコードを記述してください。

var quizTotal = 5

 

5問しか問題数がないので、5を代入します。

STEP.7
画面遷移する処理

48行目あたりのnextQuizメソッドを以下のように書き換えましょう。

func nextQuiz() {
    quizCount += 1
    quizArray.removeAll()
    if quizCount < quizTotal {
        quizArray = csvArray[quizCount].components(separatedBy: ",")
        quizNumberLabel.text = "第\(quizCount + 1)問"
        quizTextView.text = quizArray[0]
        answerBtn1.setTitle(quizArray[2], for: .normal)
        answerBtn2.setTitle(quizArray[3], for: .normal)
        answerBtn3.setTitle(quizArray[4], for: .normal)
        answerBtn4.setTitle(quizArray[5], for: .normal)
    } else {
        performSegue(withIdentifier: "score", sender: nil)
    }
}

 

簡単に解説

if quizCount < quizTotal {:もし、現在の問題番号が、問題数より少なかったら、問題をセット

} else {:そうでなかったら

performSegue(withIdentifier: "score", sender: nil)セグエIDが”score”の画面遷移をする

STEP.8
実行して確認

問題5問を終えると、スコア画面に遷移するはずです。

完了

上記のことを確認できたら、Part4の講座は終了です!

ここまでの全コード

注意

コメントは削除しているので、今後の講座で行がずれてしまう可能性があります。

import UIKit

class QuizViewController: UIViewController {

    @IBOutlet weak var quizNumberLabel: UILabel!
    @IBOutlet weak var quizTextView: UITextView!
    @IBOutlet weak var answerBtn1: UIButton!
    @IBOutlet weak var answerBtn2: UIButton!
    @IBOutlet weak var answerBtn3: UIButton!
    @IBOutlet weak var answerBtn4: UIButton!

    var csvArray: [String] = []
    var quizArray: [String] = []
    var quizCount = 0
    var quizTotal = 5

    override func viewDidLoad() {
        super.viewDidLoad()
        csvArray = loadCSV(fileName: "quiz")
        print(csvArray)
        quizArray = csvArray[quizCount].components(separatedBy: ",")
        quizNumberLabel.text = "第\(quizCount + 1)問"
        quizTextView.text = quizArray[0]
        answerBtn1.setTitle(quizArray[2], for: .normal)
        answerBtn2.setTitle(quizArray[3], for: .normal)
        answerBtn3.setTitle(quizArray[4], for: .normal)
        answerBtn4.setTitle(quizArray[5], for: .normal)
    }

    @IBAction func btnAction(sender: UIButton) {
        if sender.tag == Int(quizArray[1]) {
            print("正解")
        } else {
            print("不正解")
        }
        nextQuiz()
    }

    func nextQuiz() {
        quizCount += 1
        quizArray.removeAll()
        if quizCount < quizTotal {
            quizArray = csvArray[quizCount].components(separatedBy: ",")
            quizNumberLabel.text = "第\(quizCount + 1)問"
            quizTextView.text = quizArray[0]
            answerBtn1.setTitle(quizArray[2], for: .normal)
            answerBtn2.setTitle(quizArray[3], for: .normal)
            answerBtn3.setTitle(quizArray[4], for: .normal)
            answerBtn4.setTitle(quizArray[5], for: .normal)
        } else {
            performSegue(withIdentifier: "score", sender: nil)
        }
    }

    func loadCSV(fileName: String) -> [String] {
        let csvBundle = Bundle.main.path(forResource: fileName, ofType: "csv")!
        do {
            let csvData = try String(contentsOfFile: csvBundle,encoding: String.Encoding.utf8)
            let lineChange = csvData.replacingOccurrences(of: "\r", with: "\n")
            csvArray = lineChange.components(separatedBy: "\n")
        } catch {
            print("エラー")
        }
        return csvArray
    }
}

クイズアプリを作ろうPert4まとめ

 

まとめ
  • quizCount += 1で現在の値に、+1する
  • SegueにIDをつけ、performSegue(withIdentifier: "score", sender: nil)で画面遷移する