Swift で xib でレイアウトされたモーダルを出す
iOSのモーダルは Android でいうActivity#startActivityForResult みたいなやつ。一旦別画面で何かやってもらって、その結果を呼び出し元で取得するようなケースで使える。
ネットで調べてもサンプルがObejctive-C ばかりだったので、Swift での実装方法をまとめてみる。
ViewController の作成
NewFile から Cocoa Touch Class を指定し、親がUIViewController, Also create XIB file にチェックを入れる。

ModalViewController のセットアップ
作成したModalViewController は以下のような感じになる。
protocol ModalViewControllerDelegate {
func modalDidFinished(text: String)
}
class ModalViewController: UIViewController {
var delegate: ModalViewControllerDelegate! = nil
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func onCloseed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
self.delegate.modalDidFinished("closed")
}
}
ここで protocol で ModalViewControllerDelegate を定義しているのは、これを呼び出し元ViewController のコールバックオブジェクトとして登録するためだ。 このコールバックオブジェクトを iOSの世界では delegate と呼ぶらしい。
今回はこのプロトコルを実装した 呼び出し元ViewController を delegate として登録し、終了時に modalDidFinished を呼び出して値を呼び出し元に返している。
呼び出し元 ViewController
モーダル呼び出し元の下準備をする。
class ViewController : UIViewController, ModalViewControllerDelegate {
let modal = ModalViewController(nibName: "ModalViewController", bundle: nil)
override func viewDidLoad() {
super.viewDidLoad()
self.modal.delegate = self
}
@IBAction func onModalOpen(sender: AnyObject) {
self.presentViewController(modal, animated: true, completion: nil)
}
func modalDidFinished(text: String) {
println(text)
}
}
self(ModalViewControllerDelegateオブジェクト) を modal の delegate に代入する。
ModalViewControllerDelegate の modalDidFinishedを実装する。ここが Modal呼び出し後に呼ばれるコールバックだ。
ModalViewController 初期化時に nibName を指定しないと xib ファイルで作った View が描画されずに真っ黒になるので注意。
終わりに
両者の間で色々と実装しなければいけない所が多々あって最初はわかりにくいかもしれないが、これは Android アプリ開発でも同じようなことをよくやるケースが多いので、マスターしておきたいところ。