String型のクラス名からUIViewControllerのインスタンスを生成する方法
画面名から画面ごとのViewControllerインスタンスを生成する方法
ヒーラー
クラス名からのクラス生成はできそうだけどUIViewControllerではひとくせあり
はじめに
画面の名前とViewControllerの名前は大抵の場合合せていることだと思います。
そこで、いくつもの画面を分岐して作成したい場合に、画面に合わせたViewControllerを共通化して作成したい場合がありました。
イメージとしては、Factoryクラスに画面名(クラス名)を渡すと相当のインスタンスを返してくれるというものです。
let firstVC = ViewControllerFactory.createViewController(classname: "First") as! FirstViewController
let secondVC = ViewControllerFactory.createViewController(classname: "Second") as! SecondViewController
対処方法
クラス名の文字列からクラスのインスタンスを生成するには、NSStringFromClassを使用すれば解決します。
例えばUIViewであれば、
let uiviewClass = NSClassFromString("UIView") as! UIView.Type
let view = uiviewClass.init()
しかし、UIViewControllerの場合は注意点があります。
クラス名の前にターゲット名が含まれている必要があります。
let myClass = NSClassFromString("MyProject.CustomViewController") as! UIViewController.Type
let viewController = myClass.init()
しかしながら、productionやdevelopなど環境ごとにターゲットを分けていると、ターゲット名を固定にする訳にもいきません。
更にターゲット名を取得する必要があります。
let targetname = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
let vcname = targetname + "." + "CustomViewController"
let myClass = NSClassFromString(vcname) as! UIViewController.Type
let viewController = myClass.init()
Bundle.main.object(forInfoDictionaryKey: "CFBundleName")でターゲット名を取得できます。
これで、目的のクラス名の文字列からViewControllerインスタンスを生成することができます。
なお、作成したFactoryクラスは以下のようなイメージです。
class ViewControllerFactory {
static func createViewController(screenname: String) -> UIViewController? {
let targetname = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
let vcname = targetname + "." + screenname + "ViewController"
guard let classType = NSClassFromString(vcname) as? UIViewController.Type else {
return nil
}
let viewController = classType.init()
return viewController
}
}