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
}
}
}