はじめに
Storyboard は画面レイアウトの作成にだけ使用して、
ViewController の初期化と画面遷移はコードでやってしまいたい人向けです。
自分はよくこんな感じにやってます。
前準備
ファイルの構成について
自分は Storyboard と ViewController は1対1になるようにしています。
なので基本的に Storyboard と ViewController の名前は同じにします。
こんな感じの構成です。
FirstViewController が遷移元の画面で、SecondViewController が遷移先の画面だと思ってください。
フォルダの構成 |
---|
このとき Storyboard 側で Custom Class の設定と、
Is Initial View Controller の設定をすることを忘れないでください。
Custom Class | Is Initial View Controller |
---|---|
ViewController について
ViewController はそれぞれこんな感じです。
例として SecondViewController の number
に数字を渡したいとします。
// FirstViewController
final class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
// SecondViewController
final class SecondViewController: UIViewController {
// ここに値渡しで数字を渡したい
var number: Int!
override func viewDidLoad() {
super.viewDidLoad()
print(number)
}
}
画面遷移
では本題に入ります。
画面遷移は Storyboard から ViewController を生成して、
ViewController の present()
もしくは NavigationController の pushViewController()
のどちらかで遷移します。
// Storyboard から遷移先の ViewController を生成
// 簡易的なコードなので強制キャストしています。
let vc = UIStoryboard(name: "SecondViewController", bundle: nil).instantiateInitialViewController() as! SecondViewController
// `present()` で遷移する場合
present(vc, animated: true, completion: nil)
// NavigationController の `pushViewController()` で遷移する場合
navigationController?.pushViewController(vc, animated: true)
値渡し
画面遷移の段階で遷移先の ViewController を生成しているので、
そこに渡してしまうだけです。
// Storyboard から遷移先の ViewController を生成
// 簡易的なコードなので強制キャストしています。
let vc = UIStoryboard(name: "SecondViewController", bundle: nil).instantiateInitialViewController() as! SecondViewController
// 遷移先の `number` に値を渡す
vc.number = 10
// ...
おまけ: ViewController の初期化を簡単にする
Storyboard から ViewController を生成するコードは冗長で、
引数に Storyboard の名前を文字列として取るのでタイプミスも発生しやすいです。
なので Storyboard の初期化、初期化した Storyboard から ViewController の生成をまとめてやってしまう Static な関数を UIViewController の Extension として追加して、より簡単に初期化できるよう拡張します。
ただし、以下の Extension は Storyboard と ViewController の名前が同じであることを前提としています。
extension UIViewController {
static func instantiate() -> Self {
guard let vc = UIStoryboard(name: String(describing: self), bundle: nil).instantiateInitialViewController() as? Self else {
fatalError("Storyboard named \(String(describing: self)) was not found.")
}
return vc
}
}
使用するときはこんな感じです。
let secondVC = SecondViewController.instantiate()