【swift】ちょい足しレシピ⑤!StoryboardのUIViewControllerを取得する方法を簡潔にしてみる
もくじ
どうもこんにちは。iOSをメインに開発しているロッキーカナイです。
本日はタイトルにあるようにStoryboardのUIViewControllerを取得する方法を簡潔にしてみたいと思います。と、言いますか自分がこのコードを書いていて、冗長だなと感じていましたので(たった二行ですがw)、これも良い機会だと思い、簡潔にしてみたので紹介します。
StoryboardにあるUIViewControllerの取得方法
まず、通常の記述はこうなります。
(Main.storyboardにViewControllerがあり、Storyboard IDはクラス名と同一とします。)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
詳しい説明をしますと、
- UIStoryboardの初期化時引数に、Storyboard名とバンドルを指定しStoryboardを取得
- そのStoryboardにあるStoryboard ID(identifier)を指定しUIViewControllerを取得
2ステップなので別にいいじゃんと思えるのですが、もっと簡潔にしちゃいましょう。
提案1、新しいStoryboardを扱うクラスを作り、そのメソッドで取得する方法
新たなクラスを作成し、そのメソッドでViewControllerを取得して返してあげるものです。
class Storyboard<T> { static func instantiateViewController(name: String, withIdentifier identifier: String) -> T { let storyboard = UIStoryboard(name: name, bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: identifier) as! T return vc } }
呼び出しは以下のようになります。
let vc = Storyboard<ViewController>.instantiateViewController(name: "Main", withIdentifier: "ViewController")
ジェネリクスを使用しキャストしているので、型指定しなくてもよいのがメリットです。
提案2、ViewControllerにStoryboardから自身を取得するプロトコルを適応する方法
ViewControllerにStoryboardから自身を取得するプロトコルを適応して返してあげるものです。
protocol StoryboardInstantiable {
}
extension StoryboardInstantiable where Self: UIViewController {
static func instantiate(name: String) -> Self {
let storyboard = UIStoryboard(name: name, bundle: nil)
return storyboard.instantiateViewController(withIdentifier: String(describing: self)) as! Self
}
}
class ViewController: UIViewController, StoryboardInstantiable {
...
}
呼び出しは以下のようになります。
let vc = ViewController.instantiate(name: "Main")
プロトコルにstaticメソッドを追加し、なおかつUIViewContollerに準拠しているものだけに対応させる記述をしております。これによりコードで生成される可能性があるUIViewContollerにプロトコルを適用することで、取得ができます。
まとめ
ほかにも方法はあるでしょうが、また今度の機会にでも記載したいと思います。
他でも使用する可能性があるコードは汎用的にしたほうが、コードもスッキリしますし、随時コードを書くよりもバグ発生を抑えられますので、良いかと思います。
本日の、ちょい足しレシピは「StoryboardのUIViewControllerを取得する方法を簡潔にしてみる」でした。