LoginSignup
1
5

More than 5 years have passed since last update.

ViewController インスタンスを Storyboard から取得する extension

Posted at

StoryboardからViewControllerのインスタンスを得る仕組みとして <#クラス#>.fromStoryboard() という共通のAPIにまとめてみました。

macOS

NSViewController.swift

import Cocoa

protocol StoryboardInstantiatable: class {

    /*
    継承クラスで以下を定義してください
    typealias StoryboardInstantiatableViewController = <#YourViewController#>
    static var storyboardName: String {
        return "<#Storyboard Name#>"
    }
    */

    associatedtype StoryboardInstantiatableViewController: NSViewController

    /// Storyboard 名を返す
    static var storyboardName: String {get}
    /// Initial View Controller をロードするには nil を返す
    static var storyboardID: String? {get}

    static func fromStoryboard(withStoryboardID storyboardID: String?) -> StoryboardInstantiatableViewController
    static func fromStoryboard() -> StoryboardInstantiatableViewController

}

extension StoryboardInstantiatable where Self: NSViewController {

    static var storyboardName: String {
        return "Main"
    }

    // デフォルト実装では View Controller 名を ID として返す
    static var storyboardID: String? {
        return "\(self)"
    }

    static func fromStoryboard() -> StoryboardInstantiatableViewController {
        return fromStoryboard(withStoryboardID: self.storyboardID)
    }

    static func fromStoryboard(withStoryboardID storyboardID: String?) -> StoryboardInstantiatableViewController {
        let sb = NSStoryboard(name: storyboardName, bundle: nil)

        if let storyboardID = storyboardID {
            return sb.instantiateController(withIdentifier: storyboardID) as! StoryboardInstantiatableViewController
        }
        else {
            return sb.instantiateInitialController() as! StoryboardInstantiatableViewController
        }
    }

}

使い方:Storyboard名のみを指定

typealiasとStoryboard名が必須です。
Initial View Controller、あるいはクラス名のStoryboard IDで自動判定します。Storyboard側でクラス名と同じものをStoryboard IDとして設定しておきましょう。

Storyboard名のみを指定

class ViewController: NSViewController, StoryboardInstantiatable {

    typealias StoryboardInstantiatableViewController = ViewController
    static var storyboardName: String {
        return "MyStoryboardName"
    }

}
呼び出し
let vc = ViewController.fromStoryboard()

使い方:Storyboard名とStoryboard IDを指定

特定のStoryboard IDでインスタンスを得ます。IDが不正だとクラッシュします。

Storyboard名のみを指定

class ViewController: NSViewController, StoryboardInstantiatable {

    typealias StoryboardInstantiatableViewController = ViewController
    static var storyboardName: String {
        return "MyStoryboardName"
    }
    static var storyboardId: String? {
        return "UltraViewController"
    }

}
呼び出し
let vc = ViewController.fromStoryboard()

使い方:Storyboard名とInitial View Controllerを指定

Storyboard IDでnilを返すとInitial View Controllerのインスタンスを得ます。うまく設定されていなければクラッシュします。

Storyboard名のみを指定

class ViewController: NSViewController, StoryboardInstantiatable {

    typealias StoryboardInstantiatableViewController = ViewController
    static var storyboardName: String {
        return "MyStoryboardName"
    }
    static var storyboardId: String? {
        return nil
    }

}
呼び出し
let vc = ViewController.fromStoryboard()

iOS

使い方は基本的に同じ。

UIViewController.swift
import UIKit

protocol StoryboardInstantiatable: class {

    /*
    継承クラスで以下を定義してください
    typealias StoryboardInstantiatableViewController = <#YourViewController#>
    static var storyboardName: String {
        return "<#Storyboard Name#>"
    }
    */

    associatedtype StoryboardInstantiatableViewController: UIViewController

    /// Storyboard 名を返す
    static var storyboardName: String {get}
    /// Initial View Controller をロードするには nil を返す
    static var storyboardID: String? {get}

    static func fromStoryboard(withStoryboardID storyboardID: String?) -> StoryboardInstantiatableViewController
    static func fromStoryboard() -> StoryboardInstantiatableViewController

}

extension StoryboardInstantiatable where Self: UIViewController {

    static var storyboardName: String {
        return "Main"
    }

    // デフォルト実装では View Controller 名を ID として返す
    static var storyboardID: String? {
        return "\(self)"
    }

    static func fromStoryboard() -> StoryboardInstantiatableViewController {
        return fromStoryboard(withStoryboardID: self.storyboardID)
    }

    static func fromStoryboard(withStoryboardID storyboardID: String?) -> StoryboardInstantiatableViewController {
        let sb = UIStoryboard(name: storyboardName, bundle: nil)

        if let storyboardID = storyboardID {
            return sb.instantiateViewController(withIdentifier: storyboardID) as! StoryboardInstantiatableViewController
        }
        else {
            return sb.instantiateInitialViewController() as! StoryboardInstantiatableViewController
        }
    }

}

1
5
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
1
5