在斯威夫特回归自我

时间:2015-06-13 07:23:02

标签: 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
    }
}

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

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

2 个答案:

答案 0 :(得分: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
}

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

答案 1 :(得分:3)

根据Tomas Camin的回答,这里是Swift 3中的UIViewController扩展名。

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
  }

}

如果故事板视图控制器标识符与其类名匹配,则只需使用名称调用类函数from(storyboard:)

let viewController = MyCustomViewController.fromStoryboard("Main")

否则,请提供标识符。

let viewController = MyCustomViewController.fromStoryboard("Main", withIdentifier: "ID")

如果您已有故事板的实例,请使用它。

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

let viewController = MyCustomViewController.fromStoryboard(storyboard, withIdentifier: "ID")