【Swift3.0対応】色彩チェックアプリを作成してみよう!⑥


【Swift3.0対応】色彩チェックアプリを作成してみよう!⑥

前回の続きです。これが最後になります!

前回まででゲーム画面の実装は9割以上終了となります。
最後は画面遷移と、異なるViewController間へのデータの受け渡し
を実装したいと思います。

【STEP11】残り時間が0秒になった際に結果表示画面に遷移する

ではゲーム画面から結果表示画面への画面遷移を実装したいと思います。

【Swift3.0対応】色彩チェックアプリを作成してみよう!①
で、ストーリーボード上で画面遷移の設定(セグエの設定)を行いました。
その際にゲーム画面から結果表示画面への遷移はマニュアルセグエで設定して、
「toResult」という識別子を設定していましたね。マニュアルセグエではこの識別子を
コードで指定することで任意のタイミングで画面遷移させることができます。

では実際にやっていきましょう。0秒になった際に画面遷移をさせたいので、
countDownメソッド内の、0秒になった際にタイマーをストップさせていた場所と
同じ場所に記述します。

countDownメソッドを以下のように変更しましょう。

    //残り時間を減らしていくメソッド
    func countDown() {
        //1秒ごとに表示する残り時間を1ずつ減らし、その数値をラベルに表示する
        timeNum = timeNum - 1
        timeLabel.text = "\(timeNum)"
        //0秒でタイマーを止める。
        if timeNum  <= 0 {
            timer.invalidate()
            
            //さらに、このタイミングで画面遷移も行う
            self.performSegue(withIdentifier: "toResult", sender: nil)    //この行を追加
        }
    }

これで結果表示画面へ遷移を行なってくれます。timer.invalidate()メソッドは
消さないようにしておいてください。結果表示画面に遷移したら画面上にはタイマーは
表示されませんが、内部ではずっとタイマーが動きっぱなしになってしまうので、
ちゃんと止めてあげてください。

【STEP12】ゲーム画面から結果表示画面にデータを受け渡す

次はゲーム画面で獲得したスコアを、遷移先の結果表示画面に受け渡す機能を
実装したいと思います。
ゲーム画面ではscoreNumというプロパティでスコアの点数を保持していますので、
そのプロパティを結果表示画面のコントローラであるResultViewControllerクラスにも
定義して、値を受け渡します。

まず、ResultViewController.swiftファイル内で、以下のようにプロパティを定義してください。

import UIKit

class ResultViewController: UIViewController {
    
    var scoreNum: Int = 0    //この部分を追加

    override func viewDidLoad() {
        super.viewDidLoad()

    }

ゲーム画面で使用していたスコアを保持するプロパティを定義します。
この例ではscoreNumという名前にして、GameViewControllerクラスと
同じ名前にしていますが、同じでなくても構いません。もちろん一緒でもOKです。

次に、GameViewControllerクラス内でデータを受けわたすコードを記述します。
イメージとしては、セグエによる画面遷移の直前に、ゲーム画面側(GameViewController)で
結果表示画面(ResultViewController)のインスタンスを生成し、そこにスコアの値を
埋め込む、ということを行います。

それでは実装してみましょう。このコードはGameViewController.swiftファイル内
新しいメソッドを記述します。
どこに記述してもいいのですが、わかりやすいようにcountDownメソッドの下辺りに書いておくと
画面遷移時の流れをイメージしやすくなると思います。

    //残り時間を減らしていくメソッド
    func countDown() {
        //1秒ごとに表示する残り時間を1ずつ減らし、その数値をラベルに表示する
        timeNum = timeNum - 1
        timeLabel.text = "\(timeNum)"
        //0秒でタイマーを止める。
        if timeNum  <= 0 {
            timer.invalidate()
            
            //さらに、このタイミングで画面遷移も行う
            self.performSegue(withIdentifier: "toResult", sender: nil)
        }
    }
    
    //ゲーム画面→結果表示画面のViewControllerにプロパティの値を渡す
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let newVC = segue.destination as! ResultViewController
        newVC.scoreNum = self.scoreNum
    }

先ほど追加コードを記述したcontDownメソッドの下にこのようにprepareメソッドをオーバライド
して記述します。prepareメソッド内で、次の画面のコントローラであるResultViewControllerの
インスタンスを生成し、そのscoreNumプロパティに自分のクラスであるGameViewControllerのscoreNum
を代入しておく、という手法で値の受け渡しをします。

もう少し詳しく説明すると、18行目の右辺にあるsegue.destinationで遷移先のViewControllerクラスの
インスタンスを取得することができます。しかし、取得したインスタンスの型はViewControllerクラスですので、
ResultViewControllerクラスで定義したscoreNumという値を使うことができません。そのためas!演算子で
ResultViewControllerクラスに強制ダウンキャストをしています。

結果としてnewVCはResultViewController型の値が代入されていることになります。
ちょっと複雑ですが、このような値渡しの手法は良く行われるので覚えておくと良いでしょう。

【STEP13】結果表示画面を実装する

最後に結果表示画面の実装です。もう一度結果表示画面をストーリーボードで見てみましょう。

図の枠線がかかっている部分の表示はゲームのスコアによって変化するので、
Outlet接続してコードを加えていきます。

それぞれscoreLabelとrankLabelという名前でOutlet接続しておきます。

次に1つメソッドを定義しましょう。ランクを表示するメソッドです。

    func showRank(num: Int) {
        var text: String
        switch num {
        case 0...10:
            text = "もっとがんばりましょう"
        case 11...20:
            text = "あと少しがんばりましょう"
        case 21...27:
            text = "正常な色彩です"
        case 26...32:
            text = "良い色彩の持ち主です"
        case 33...37:
            text = "素晴らしい色彩の持ち主です"
        default:
            text = "神レベル"
        }
        rankLabel.text = text
    }

※これは筆者が勝手に考えたランク分けです。このランクは任意で変更してください。

最後に、この定義したメソッドとスコアを表示するラベルを、viewDidLoadメソッド内で
書き換えてあげて終わりです!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.resultScoreLabel.text = String(scoreNum)
        showRank(num: scoreNum)
    }

これで完成!!お疲れ様でしたーー!!!

  • このエントリーをはてなブックマークに追加

PAGE TOP