46
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UIStoryboardからViewControllerをロードするときにenumとprotocolとextensionを使ってカッコよくやる方法

Posted at

よくあるやり方

let name = "Main"
let identifier = "ArticleViewController"
let storyboard = UIStoryboard(name: name, bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier(identifier) as! ArticleViewController
  • このまま乱立すると、nameやidentifierの管理コストがひどい
  • as! でキャストするのはswiftでコード書いてると気持ち悪い感が。。

こういうふうに書けるようにできます

let storyboard = UIStoryboard(storyboard: .Main)
let viewController: ArticleViewController = storyboard.instantiateViewController()

定義方法

Storyboardのidentifierをプロパティとしてもつprotocolを定義します。

protocol StoryboardIdentifiable {
    static var storyboardIdentifier: String { get }
}

protocol extensionで初期値はUIViewControllerのクラス名がidentifierとなるように定義します。
そのため、Storyboard IDは定義しているViewControllerと同じ名前を使うようにしてください。(一番上の例だとStoryboard ID = "ArticleViewController" となります)

extension StoryboardIdentifiable where Self: UIViewController {
    static var storyboardIdentifier: String {
        return String(self)
    }
}

UIViewControllerにStoryboardIdentifiableを適合させます。

extension UIViewController: StoryboardIdentifiable { }

UIStoryboardを拡張します。

extension UIStoryboard {
    // アプリ内で作成されているStoryboardの名前をenumで定義します
    enum Storyboard: String {
        case Main
        case News
        case Favorite
    }

    // 上で定義したenumでinitできるように
    convenience init(storyboard: Storyboard, bundle: NSBundle? = nil) {
        self.init(name: storyboard.rawValue, bundle: bundle)
    }

    // StoryboardIdenfiableプロトコルに適合してるUIViewControllerのみ
    func instantiateViewController<T: UIViewController where T: StoryboardIdentifiable>() -> T {
        // ジェネリクスでプロトコルに適合してるのは保証される
        let optionalViewController = self.instantiateViewControllerWithIdentifier(T.storyboardIdentifier)

        guard let viewController = optionalViewController as? T else {
            fatalError("something error")
        }

        return viewController
    }
}

UIViewControllerの継承はいつも通りで使えるようになります。

class ArticleViewController: UIViewController { }

参考リンク

UIStoryboard: Safer with Enums, Protocol Extensions and Generics — Swift Programming — Medium

46
44
0

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
46
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?