読者です 読者をやめる 読者になる 読者になる

いものやま。

雑多な知識の寄せ集め

変種オセロのスタート画面を作ってみた。(その7)

昨日はゲーム画面からスタート画面への遷移を作った。

今日は遷移するときに確認のダイアログを出すようにしていく。

UIAlertController

確認のダイアログを出すときに使えるのが、UIAlertController。
(なお、以前はUIAlertViewが使われていたけれど、非推奨(Deprecated)になっているので、使わない方がいい)

UIAlertControllerでは2種類のビューのスタイルが利用できて、一つはアクションシート(ActionSheet)、もう一つはアラート(Alert)。
ダイアログを出したい場合、後者を使うといい。

確認ダイアログの表示

ということで、さっそく実装。

//==============================
// YWF
//------------------------------
// GameScene.swift
//==============================

import SpriteKit

public class GameScene: SKScene, ButtonNodeObserver {
  // 省略

  public func buttonIsSelected(button: ButtonNode) {
    let dialog = UIAlertController(title: nil,
                                   message: "Do you really want to leave this game?",
                                   preferredStyle: .Alert)
    dialog.addAction(UIAlertAction(title: "Yes", style: .Default,
                                   handler: {
                                     (action:UIAlertAction!) -> Void in
                                     let scene = StartScene(size: self.size)
                                     let transition = SKTransition.fadeWithDuration(NSTimeInterval(1.0))
                                     self.view?.presentScene(scene, transition: transition)
                                   }))
    dialog.addAction(UIAlertAction(title: "No", style: .Cancel, handler: nil))
    self.view?.window?.rootViewController?.presentViewController(dialog, animated: true, completion: nil)
  }
  
  // 省略
}

まず、UIAlertControllerのインスタンスを作成。
スタイルは前述した通り、アラート。

そして、そこにアクション(UIAlertAction)を追加していく。
ボタンが押されたときの処理はクロージャで記述する。

最後に、作成したダイアログの表示。
UIAlertControllerはUIViewControllerを継承しているので、UIViewController#presentViewController(_: UIViewController, animated: Bool, completion: (() -> Void)?)の引数に指定してダイアログを表示させる。
じゃあ、レシーバのUIViewControllerは何にすればいいのかというと、ダイアログを表示させようとしているビューコントローラ・・・なわけだけど、SpriteKitを使っている場合、ちょっと困ってしまう。
というのも、SpriteKitの場合、ビューコントローラとビューという関係は、ビューの中のシーンとノードという関係になっているので、ビューコントローラはビューの内側のシーンやノードにはノータッチで、それゆえ、シーンやノードも自身を表示させている大元のビューコントローラを知ることが出来ないから。

一つの方法としては、ビューコントローラから最初のシーンを作るときに、ビューコントローラへの参照をシーンに渡しておいて、非所有参照でそれを保持しておくということが考えられる。(非所有参照(あるいは弱い参照)にしておかないと、参照がループするので注意)
ただ、それだと辻褄を無理やり合わせている感じがして、ちょっと微妙。

もう一つの方法は、自分がやった方法。
これもかなり無理やりな感じだけど、つまり、現在のウィンドウの根っこのビューコントローラに表示させるという方法。
まぁ、ダイアログがモーダルであることを考えると、ウィンドウ自体にダイアログを表示させるという考え方は、それほど間違いではないはず。

動作確認

さて、これで実際に動かしてみると、どんな感じなのか。

ちゃんと確認ダイアログが表示されて、"No"をクリックしたときには何も起きず、"Yes"をクリックしたときにだけスタート画面に戻っているのが分かると思う。

今日はここまで!