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

サトリク

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

今の状態

サトリク

スタートボタンを押すと、問題画面に遷移し、Buttonを押すとコンソールに押したボタンの番号が表示されます。

今回は、このLabelに問題数、Text Viewに問題、Buttonに選択肢を表示していきたいと思います。

では早速クイズアプリPart3をやっていきましょう!

 

 

問題データ(CSVファイル)作成

サトリク

まずは問題を作成します。

今回のクイズアプリでは、問題のデータはCSVファイル(カンマ区切りのファイル)で作ります。

CSVファイルとは?

CSVとは「Comma Separated Valueカンマ セパレーテッド バリュー」の略で、,(カンマ)で区切られた(セパレーテッド)値(バリュー)ということです。

 

 

問題データは、問題文、正解番号、選択肢1、選択肢2、選択肢3、選択肢4を入れていきたいと思います。

つまり、こんな感じのファイルを作成します。

問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4
問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4
問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4
問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4
問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4

 

STEP.1
ファイル作成

Emptyを選択する画像

Xcodeを開き、command + nでファイル作成ウィンドウを表示

①下の方にある「Empty」を選択

②「Next」をクリック

STEP.2
ファイル名、保存先選択

①「Save As:」にquiz.csvと入力

②「Create」をクリック

STEP.3
問題データをcsvファイルに入力

書き方は、問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4です。

最低5問用意しましょう。

 

注意!

正解番号は「選択肢1なら0」「選択肢2なら1」「選択肢3なら2」「選択肢4なら3」です。

少しややこしいですが、間違えないようにしましょう。

 

サトリク

自分で問題を作成してもいいですが、問題を考えるのがめんどくさいという方のために

しょうもないクイズを用意しました。

こちらをコピペしてください。

 

ぼうしの中に入っている動物はなに?,3,かめ,ウサギ,キリン,うし
飲むとおこられるジュースってなに?,0,コーラ,サイダー,オレンジ,ピーチ
おいしくて甘い てら ってどんなてら?,2,リンゴ,かき,カステラ,ホットケーキ
いつも文句ばかり言っている動物はなに?,3,いのしし,ぞう,さい,うし
とってもつめたい いす ってなに?,1,こおり,アイス,ふぶき,れいぞうこ
完了

これで問題データ作成は完了です。

CSVファイルを読み込むプログラムを作成

先ほど作成した問題データを取り込むプログラムを作成しましょう。

ここでは、超初心者の方はそこまで内容は理解しなくてもいいです。僕も最初は全くわかりませんでした。こういうもんなんだなぁ程度でやりましょう。

STEP.1
QuizViewControllerを開く

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

STEP.2
csvファイルを格納する配列宣言

20行目あたり(IBOutlet〜〜override func viewDidLoad()の間)に以下コード(宣言)を記述します。

var csvArray: [String] = []

 

ここでは、配列を宣言しています。配列というのは複数の要素(値)をしまえる箱だと思ってください。

この箱にcsvファイルのデータを入れていきたいと思います。

STEP.3
配列(csvArray)ににデータをいれる

33行目あたり(}/*の間)に以下のコード(関数)を記述します。

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
}

 

STEP.4
関数を呼び出す処理

24行目あたり(super.viewDidLoad()の下)に以下のコードを追加しましょう。

csvArray = loadCSV(fileName: "quiz")
print(csvArray)

 

基本的なことですが、print(csvArray)というのは、コンソール上にcsvArrayの情報を表示するという意味です。

STEP.5
実行して確認する

command + rで実行して確認してみましょう。

実行してスタートボタンを押した瞬間に、コンソールに問題データが表示されるはずです。

完了

サトリク

上記のように確認できたら完了です!

 

問題文と選択肢を表示するプログラムを作成

次は、csvファイルデータを問題文や選択肢に表示させるプログラムを作成したいと思います。

記述するファイルは、先ほどと同じくQuizViewController.swiftです。

STEP.1
csvファイルから取り出した問題を格納する配列・変数宣言

21行目あたり(var csvArray: [String] = []の下)に以下のコード(配列・変数宣言)を記述します。

var quizArray: [String] = []
var quizCount = 0

 

2つの箱を用意します。

  • quizArrayは、問題データの1問ずつデータをいれる箱
  • quizCountは、現在の問題数を表示するための箱
STEP.2
問題を表示させる

28行目あたり(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)

 

 

簡単に解説

一行目のquizArray = csvArray[quizCount].components(separatedBy: ",")は、
quizArrayに、quizCount行(現在は0)を格納します。

 

二行目のquizNumberLabel.text = "第\(quizCount + 1)問"は、
Part2で紐付けたquizNumberLabelのテキストに「第\(quizCount + 1)問」をいれるという意味です。

 

三行目のquizTextView.text = quizArray[0]は、
Part2で紐付けたquizTextViewのテキストに、問題データの一行(問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4)の0番目の問題文をいれるという意味です。

 

四行目以降のanswerBtn1.setTitle(quizArray[2], for: .normal)は、
Part2で紐付けたanswerBtnのタイトルに、問題データの一行の2番目以降のデータをいれるという意味です。

STEP.3
実行して確認する

command + rで実行して確認してみましょう。

このように、問題数、問題文、選択肢1、選択肢2、選択肢3、選択肢4が表示されていれば成功です。

注意

今回のアプリでは、iPhone11向けに作成しているので、iPhone11以外のシミュレーターで起動すると、レイアウトが崩れる場合があります。

後々のパートで修正するかも。。

完了

上記のことが確認できたら、このPartは成功です。

次のPartにいきましょう!

ここまでの全コード

注意

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

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

    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) {
        //ボタンを押したときに呼ばれる
        print(sender.tag)
    }

    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
    }
}

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

 

まとめ
  • CSVファイルとは、,(カンマ)で区切られた(セパレーテッド)値(バリュー)のこと
  • var array: [String] = []で配列の宣言
  • var quizCount = 0で変数の宣言
  • label.text = "文字"でstoryboardと紐づいているlabelに文字を入れる
  • textView.text = "文字列"でstoryboardと紐づいているtextViewに文字を入れる
  • button.setTitle("文字列", for: .normal)でstoryboardと紐づいているButtonのタイトルに文字を入れる