Swift3 UIViewControllerをStoryboardから呼び出すいい感じなExtension

# バージョン
Xcode 8.3.2
Swift 3.1

# 参考
> https://github.com/to4iki/conference-app-2017-ios/blob/f303d2e02e3d6f2c4638049c3389e4d6a13b6286/conference-app-2017/data/extension/UIViewControllerExtension.swift

※参考ってかほぼコピペ

# 本題

```Swift:UIViewControllerExtension.swift
protocol StoryBoardInstantiatable {}

extension StoryBoardInstantiatable where Self: UIViewController {

    static func instantiate() -> Self {
        let bundle = Bundle(for: self.self)
        let subName = self.removeViewControllerAtTheEndOf(str: String(describing: self.self))
        
        guard let vc = UIStoryboard(name: subName, bundle: bundle).instantiateInitialViewController() as? Self else {
            fatalError("エラー：StoryboardからVCの取得に失敗しました。Storyboard Name: \(subName)")
        }
        
        return vc
    }
    
    static func instantiateWithIdentifier(_ identifier: String = String(describing: Self.self)) -> Self {
        let bundle = Bundle(for: self.self)
        let subName = self.removeViewControllerAtTheEndOf(str: String(describing: self.self))
        
        guard let vc = UIStoryboard(name: subName, bundle: bundle).instantiateViewController(withIdentifier: identifier) as? Self else {
            fatalError("エラー：StoryboardからVCの取得に失敗しました。Storyboard Name: \(subName), Identifier: \(identifier)")
        }
        
        return vc
    }
    
    static func instantiateEmbedInNavigationController() -> UINavigationController {
        let vc = self.instantiate()
        let nav = UINavigationController(rootViewController: vc)
        
        return nav
    }
    
    static func instantiateEmbedInNavigationControllerWithIdentifier(_ identifier: String = String(describing: Self.self)) -> UINavigationController {
        let vc = self.instantiate()
        let nav = BaseNavigationController(rootViewController: vc)
        
        return nav
    }
    
    static private func removeViewControllerAtTheEndOf(str: String) -> String {
        return str.replacingOccurrences(of: "ViewController$", with: "", options: .regularExpression, range: nil)
    }
}

extension UIViewController: StoryBoardInstantiatable {}
```

# 使い方

SampleViewController クラスの instantiate メソッドから呼び出す Storyboard は Sample.storyboard になります。
ViewController を除いた名前を Storyboard名 にしてください。気に入らない場合は Extension の `removeViewControllerAtTheEndOf` メソッドを修正してください。

```Swift:使い方.swift
// MARK: - UIViewController

// Sample.storyboard の isInitial に設定されている ViewController を取得します
let vc = SampleViewController.instantiate()
// Sample.storyboard の Identifier に SampleViewController が設定されている ViewController を取得します
let vc = SampleViewController.instantiateWithIdentifier()
// Sample.storyboard の Identifier に TestViewController が設定されている ViewController を取得します
let vc = SampleViewController.instantiateWithIdentifier("TestViewController")

// MARK: - UINavigationController

// 下記は上記で取得したViewControllerをUINavigationControllerのrootに設定して、NavigationControllerを返すメソッドです
let vc = SampleViewController.instantiateEmbedInNavigationController()
let vc = SampleViewController.instantiateEmbedInNavigationControllerWithIdentifier()
let vc = SampleViewController.instantiateEmbedInNavigationControllerWithIdentifier("TestViewController")

```