追記
iOS - 構造体でStoryboardとNibを管理する - Qiitaの方が1箇所にリソースの定義をまとめられて分かりやすいかもしれません。
Swift - StoryboardやXibファイルからインスタンスを生成するprotocol - Qiitaという記事を拝見して、そのProtocolを改造した。
protocol Instantiatable {
typealias InstanceType
static func instantiateFromResource(resourceName: String?, identifier: String?) -> InstanceType!
}
protocol ResourceBundleProvider {
static var resourceBundle: NSBundle { get }
}
extension ResourceBundleProvider {
static var resourceBundle: NSBundle { return NSBundle.mainBundle() }
}
protocol StoryboardInstantiatable: Instantiatable, ResourceBundleProvider {
typealias InstanceType = Self
static var storyboardName: String { get }
static var viewControllerIdentifier: String? { get }
}
extension StoryboardInstantiatable {
static var storyboardName: String { return "" }
static var viewControllerIdentifier: String? { return nil }
static func instantiateFromResource(resourceName: String? = nil, identifier: String? = nil) -> InstanceType! {
let name = resourceName ?? storyboardName
let identifier = identifier ?? viewControllerIdentifier
let storyboard = UIStoryboard(name: name, bundle: resourceBundle)
if let identifier = identifier {
return storyboard.instantiateViewControllerWithIdentifier(identifier) as! InstanceType
} else {
return storyboard.instantiateInitialViewController() as! InstanceType
}
}
}
protocol NibInstantiatable: Instantiatable, ResourceBundleProvider {
typealias InstanceType = Self
static var nibName: String { get }
}
extension NibInstantiatable {
static var nibName: String { return "" }
static func instantiateFromResource(resourceName: String? = nil, identifier: String? = nil) -> InstanceType! {
let name = resourceName ?? nibName
let nib = UINib(nibName: name, bundle: resourceBundle)
return nib.instantiateWithOwner(nil, options: nil).first as! InstanceType
}
}
使い方
StoryboardInstantiatableの使い方
UIViewControllerをStoryboardInstantiatableに以下のように適合させる。storyboardNameというクラス変数にストーリーボード名を設定するだけ。instantiateメソッドにストーリーボード名を直接渡す場合はstoryboardNameは必要ない。
class SampleViewController: UIViewController, StoryboardInstantiatable {
static var storyboardName = "Sample"
インスタンスを得るには以下のようにする。instantiateにストーリーボード名を渡すと、そのストーリーボードが利用される。Storyboard名を渡すとstoryboardNameが設定されていても引数のStoryboard名が優先されて利用される。
Storyboard ID(引数名: identifier)を渡すと、instantiateViewControllerWithIdentifier(_)でインスタンス化が行われる。指定しないとviewControllerIdentifierクラス変数が利用される。引数でもクラス変数でもidentifierが指定されない場合はinstantiateInitialViewController()が利用される。
let controller = SampleViewController.instantiateFromResource()
let controllerInOtherStoryboard = SampleViewController.instantiateFromResource("Other")
let controllerWithIdentifier = SampleViewController.instantiateFromResource("Other", identifier: "SecondViewController")
NibInstantiatableの使い方
UIViewをNibInstantiatableに以下のように適合させる。nibNameというクラス変数にNib名を設定するだけ。ただし変数の型は明示する必要がある。Storyboardと同様にinstantiateメソッドにストーリーボード名を直接渡す場合はnibNameは必要ない。
class SampleView: UIView, NibInstantiatable {
static var nibName = "SampleView"
インスタンスを得るには以下のようにする。
let sampleView = SampleView.instantiateFromResource()
let sampleViewOnOtherNib = SampleView.instantiateFromResource("OtherView")