在斯威夫特回归自我

Faw*_*kes 12 ios swift

目的:制作一个通用的ViewController和TableViewController,它能够从现有的故事板中返回自己,并由其他视图控制器进行子类化,并允许它们使用此功能.

class GenericTableViewController: UITableViewController
{
    //MARK: Storyboard
    class func storyboardName() -> String
    {
        return ""
    }

    class func storyboardIdentifier() -> String
    {
        return ""
    }

    class func existingStoryboardControllerTemplate() -> Self
    {
        return  UIStoryboard.storyboardWithName(storyboardName()).instantiateViewControllerWithIdentifier(storyboardIdentifier()) as! Self
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是..编译器强迫我将Self更改为此"GenericTableViewController",如果我更改它...它抱怨我不再返回"Self".

有什么东西能解决这个问题吗?

Tom*_*min 23

执行以下操作应该有效:

class func existingStoryboardControllerTemplate() -> Self {
    return  existingStoryboardControllerTemplate(self)
}

private class func existingStoryboardControllerTemplate<T>(type: T.Type) -> T {
    return  UIStoryboard(name: storyboardName(), bundle: nil).instantiateViewControllerWithIdentifier(storyboardIdentifier()) as! T
}
Run Code Online (Sandbox Code Playgroud)

基本上你创建了一个通用版本existingStoryboardControllerTemplate并添加了一个额外的方法来帮助编译器推断出它的类型T.


Bra*_*rie 5

基于 Tomas Camin 的答案,这里有UIViewControllerSwift 3 的扩展。

extension UIViewController {

  class func fromStoryboard(_ name: String, in bundle: Bundle? = nil, withIdentifier id: String? = nil) -> Self? {
    return fromStoryboard(UIStoryboard(name: name, bundle: bundle), withIdentifier: id)
  }

  class func fromStoryboard(_ storyboard: UIStoryboard, withIdentifier id: String? = nil) -> Self? {
    return fromStoryboard(storyboard, withIdentifier: id, as: self)
  }

  private class func fromStoryboard<T>(_ storyboard: UIStoryboard, withIdentifier id: String? = nil, as type: T.Type) -> T? {
    return  storyboard.instantiateViewController(withIdentifier: id ?? "\(type)") as? T
  }

}
Run Code Online (Sandbox Code Playgroud)

如果您的故事板视图控制器标识符与其类名称匹配,则只需使用fromStoryboard(name:)名称调用类函数即可。

let viewController = MyCustomViewController.fromStoryboard("Main")
Run Code Online (Sandbox Code Playgroud)

否则,请提供标识符。

let viewController = MyCustomViewController.fromStoryboard("Main", withIdentifier: "ID")
Run Code Online (Sandbox Code Playgroud)

如果您已经有故事板的实例,则可以使用它。

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

let viewController = MyCustomViewController.fromStoryboard(storyboard, withIdentifier: "ID")
Run Code Online (Sandbox Code Playgroud)