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

サトリク

前回の講座を受けていない方はこちらから

 

今の状態

サトリク

今の状態は、スタートボタンを押すと、問題画面に遷移し、Buttonを押すとコンソールに押したボタンの番号が表示される。という状態です。

このPartでは、まず問題のデータを作成し、問題画面のLabelに問題数、TextViewに問題文、Buttonに選択肢を表示させていきたいと思います。

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

 

 

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

 

サトリク

まず、問題データを作成します。

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

CSVファイルとは?

CSVとは「Comma Separated Valueカンマ セパレーテッド バリュー」の略で、,(カンマ)で区切られた(セパレーテッド)値(バリュー)という意味です。要はカンマ区切りのデータの集まりのファイルです。

例えばこんな感じです。

色,赤,白,黄,青,黒,紫,ピンク,グレー
サイズ,SS,S,M,L,LL,3L,フリー
商品名,Tシャツ,ポロシャツ,ジャケット,コート
種別,メンズ,レディース,男女共用,キッズ
メーカー名,メーカーA,メーカーB,メーカーC,メーカーD,メーカーE
価格,1000円,1500円,2000円,3000円,5000円,10000円

このように問題文と選択肢と正解番号を記載したcsvファイルを作って、そのファイルから取得してLabelやTextField、Buttonに表示させるプログラムを記述して表示させていきたいと思います。

STEP.1
ファイル作成

まずはcsvファイルを作成します。

command + nで新規ファイルウィンドウを表示させます。

①Emptyを選択

②Nextをクリック

STEP.2
ファイル名と保存先

①ファイル名にquiz.csvと入力

②Createをクリック

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

作成したcsvファイルに問題データを入れましょう。

以下のように、「問題文,正解番号,選択肢1,選択肢2,選択肢3,選択肢4」という形で書いてください。最低5問は作成してください。

 

とりあえず問題は後で考えるという方は以下の問題を使ってください。

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

 

こんな感じになればOKです。

完了

これで、問題データが完成しました。

次はこれを読み込むプログラムを書いていきましょう。

 

問題データを読み込むプログラムを作成

まずはデータを読み込んで、コンソールに表示させてみましょう。

STEP.1
QuizViewController.swiftを選択

左のメニューからQuizViewController.swiftを選択してください。

STEP.2
データを入れる箱を作る

まずは、csvファイルから読み込んだデータを入れる箱を用意します。

classの下に以下のコードを記述してください。

var csvArray: [String] = []

この1行でcsvArrayという配列の箱を用意しました。この箱にcsvファイルから読み込んだ値を入れていきます。

STEP.3
csvファイルを読み込むブロック

まずはcsvファイルを読み込むブロックを記述します。

@IBOutletのブロックの下に、以下のブロックを記述してください。

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")
        csvArray.removeLast()
    } catch {
        print("エラー")
    }
    return csvArray
}

ここのブロックの内容少し難しいので、このブロックを呼べばcsvファイルが読み込まれるんだなぁ程度の理解で大丈夫です。

STEP.4
csvファイル読み込むブロックを呼び出す

次に、csvファイルを読み込むブロックを呼び出し、先ほど用意した箱(csvArray)に代入します。そしてコンソールに表示させます。

画面を表示した時に呼ばれるViewDidLoad()ブロックに以下のコードを記述してください。

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

STEP.5
実行して確認

左上の再生ボタンを押して実行して、スタートボタンを押してください。

画面を表示した時に呼ばれるブロック(ViewDidLoad())でprint(csvArray)と記述しているので、以下のように画面を表示した瞬間にcsvファイルから読み込んだ問題のデータがコンソールに表示されると思います。

完了

これでcsvファイルから問題データを読み込むことができました。

 

問題データを画面に表示させる

では、次は読み込んだ問題データを画面に表示させていきましょう。

STEP.1
Main.storyboardを選択

コードからlabelなどに表示する文字を代入するので、Storyboardとプログラムファイルを紐づけていきましょう。

Main.storyboardを選択

STEP.2
問題数を表示するLabelを紐付け

プログラムファイルと2分割されていない場合は、問題画面の上のバーをクリックしてcommand + option + control + enterで2分割にしてください。

Labelをcontrolを押しながら、classの下にドラッグ&ドロップしてください。

 

NameにquizNumberLabelと入力してConnect

STEP.3
問題文を表示させるTextViewを紐付け

controlを押しながら、TextViewを@IBOutletの下にドラッグ&ドロップ

 

NameにquizTextViewと入力し、Connect

STEP.4
選択肢を表示するButtonを紐付け

controlを押しながら、Buttonを@IBOutletの下にドラッグ&ドロップ

 

NameにanswerButton1と入力し、Connect

STEP.5
同じように他のボタンも紐付け

同じように、選択肢2はNameにanswerButton2、選択肢3はNameにanswerButton3、選択肢4はNameにanswerButton4で紐付けてください。

このような感じになればOKです。

STEP.6
QuizViewController.swiftを選択

QuizViewController.swiftを選択してください。

STEP.7
1問分のデータを入れる箱を作る

まずは、1問分のデータを入れる箱を作ります。それと問題数をカウントする変数も作っておきます。

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

STEP.8
quizArrayに1問分のデータを入れる

最初に表示する画面で必要なデータは、1問目の問題文と選択肢1と選択肢2と選択肢3と選択肢4です。

なので、csvArray(全てのデータ)から1問目のデータのみをquizArrayに代入します。

viewDidLoar()の中のprint(csvArray)の下に以下のコードを記述してください。

quizArray = csvArray[quizCount].components(separatedBy: ",")

STEP.9
Label、TextView、Buttonに代入

先ほど紐付けたオブジェクトにデータを代入していきます。

先ほど記述したquizArray = csv~~の下に以下のコードを記述してください。

quizNumberLabel.text = "第\(quizCount + 1)問"
quizTextView.text = quizArray[0]
answerButton1.setTitle(quizArray[2], for: .normal)
answerButton2.setTitle(quizArray[3], for: .normal)
answerButton3.setTitle(quizArray[4], for: .normal)
answerButton4.setTitle(quizArray[5], for: .normal)

代入時のquizArray[ぼうしの中に入っている動物はなに?,4,かめ,ウサギ,キリン,うし]です。

quizArray[0]は問題文を取得できて、

quizArray[2]は選択肢の1番目が取得、

quizArray[3]は選択肢の2番目が取得、

quizArray[4]は選択肢の3番目が取得できるということになります。

それらをそれぞれTextViewやLabel、Buttonに代入しています。

STEP.10
実行して確認

左上の再生ボタンで実行して確認しましょう。

このように、問題番号、問題文、選択肢が表示されると思います。

注意

現状、iPhone11以外のシミュレーターで起動すると、レイアウトが崩れる場合があります。

なので他の端末に対応するまで、iPhone11で実行してください。

完了

これで、csvファイルからデータを取得して画面に表示させることができました。

 

ここまでの全コード

import UIKit

class QuizViewController: UIViewController {
    @IBOutlet var quizNumberLabel: UILabel!
    @IBOutlet var quizTextView: UITextView!
    @IBOutlet var answerButton1: UIButton!
    @IBOutlet var answerButton2: UIButton!
    @IBOutlet var answerButton3: UIButton!
    @IBOutlet var answerButton4: 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]
        answerButton1.setTitle(quizArray[2], for: .normal)
        answerButton2.setTitle(quizArray[3], for: .normal)
        answerButton3.setTitle(quizArray[4], for: .normal)
        answerButton4.setTitle(quizArray[5], for: .normal)

        // Do any additional setup after loading the view.
    }
    
    //ボタンを押したときに呼ばれる
    @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")
            csvArray.removeLast()
        } catch {
            print("エラー")
        }
        return csvArray
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

 

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

 

まとめ
  • CSVファイルとは、,(カンマ)で区切られた(セパレーテッド)値(バリュー)のファイルのこと
  • controlを押しながら、オブジェクトをドラッグ&ドロップで紐付け

 

一緒に楽しく雑談しながらアプリ開発しませんか?

RikutoSato

satorikublogの筆者がアプリ開発をマンツーマンでサポートします。

あなたのクイズアプリをAppStoreにリリースするまで、チャットや、ビデオ通話で楽しく雑談でもしながらサポートします。エラーで先に進まない方や、アイデアはあるけど、そのアイデアをアプリに実現できない方など、気軽にご相談ください!

詳しくはこちら