SwiftでStoryboardとXibをシンプルに呼び出す
StoryboardとXibの呼び出し方が面倒
コードからStoryboardやXibを呼びだそうとすると以下のような煩わしい書き方になります。
// load view from xib let sampleView = UINib(nibName: "SampleView", bundle: nil).instantiateWithOwner(self, options: nil)[0] as! SampleView // load view controlelr from storyboard let storyboard = UIStoryboard(name: "Sample", bundle: nil) let sampleViewController = storyboard.instantiateViewControllerWithIdentifier("SampleViewController") as! SampleViewController
まず何が煩わしいかというと、長ったらしくて覚えてられんということ。そしてas!で強制アンラップしているので、Swift的にあまりよろしくありません。as?にしてif let, guard let elseで書くのもありですが、毎回書くのは面倒です。
Protocolを使って簡易的な呼び方ができるようにする
Protocolを使い、上記の長ったらしい部分を簡略化してみます。「Xib, Storyboardを簡易的に呼べる」というProtocolを作成してみました。
protocol NibLoadable { static var nibName: String { get } } extension NibLoadable { static var nibName: String { return String(self) } } extension UINib { static func instantiateView<T:UIView where T:NibLoadable>() -> T { guard let view = UINib(nibName: T.nibName, bundle: nil).instantiateWithOwner(self, options: nil)[0] as? T else { fatalError("cannot load nib") } return view } } protocol StoryboardLoadable { static var storyboardIdentifier:String { get } static var storyboardName:String { get } } extension StoryboardLoadable { static var storyboardIdentifier:String { return String(self) } } extension UIStoryboard { static func instantiateViewController<T:UIViewController where T:StoryboardLoadable>() -> T { guard let viewController = UIStoryboard(name: T.storyboardName, bundle: nil).instantiateViewControllerWithIdentifier(T.storyboardIdentifier) as? T else { fatalError("cannot load storyboard") } return viewController } }
使い方
SampleViewクラスをNibloadableに準拠させると下記のようにシンプルにXibからViewをロードすることができます。
let sampleView: SampleView = UINib.instantiateView()
Storyboardも同様です。
let sampleViewController: SampleViewController = UIStoryboard.instantiateViewController()
注意点
- Xibのファイル名とViewのクラス名を同じにしておく
- StoryboardのIdentifierとViewControllerのクラス名を同じにしておく
上記の2点を満たす必要があります。もしこれらを別名で管理している場合は、上記のProtocolにその情報を扱うプロパティを追加してあげて実装するとよいかと。