LoginSignup
30
28

More than 5 years have passed since last update.

Protocolを利用してStoryboardやXibファイルからインスタンスを生成する

Last updated at Posted at 2015-09-28

追記
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")
30
28
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
28