通过覆盖它的指定初始化器从情节提要中获取 UIVIewController

Getting a UIVIewController from a storyboard by overriding it's designated initializer

在 Objective-C 中,我经常像这样覆盖我的 UIViewController subclass 的 init

- (id)init
{
    self = [[UIStoryboard storyboardWithName:@"..." bundle:nil] instantiateViewControllerWithIdentifier:@"..."];
    return self;
}

这样当我需要使用它时,我可以简单地调用id controller = [MyViewController new]

是否可以在 Swift 中做类似的事情,以便我可以调用 let controller = MyViewController() 从故事板实例化视图控制器?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    // you can't assign self
    self = UIStoryboard(name: "...", bundle: nil).instantiateViewControllerWithIdentifier("...")

    // you can't return anything other than nil
    return UIStoryboard(name: "...", bundle: nil).instantiateViewControllerWithIdentifier("...")
}

我知道我可以拥有 class 功能

class func controller -> instancetype {
    return UIStoryboard(name: "...", bundle: nil).instantiateViewControllerWithIdentifier("...")
}

但是调用 MyViewController.controller() 并不像 MyViewController() 那样直接-如果我永远不会在没有情节提要的情况下使用 MyViewController,那么 指定初始化器?

您将分配与初始化混合在一起。

init 初始化已分配的对象。

instantiateViewControllerWithIdentifier: 实例化(分配和初始化)视图控制器对象。

简而言之,工厂方法是 alloc init 的替代品。

尝试在 init 中调用 instantiate 就像调用 [[[[Class alloc] init] alloc] init] 一样。你所做的(在你的 Objective C 代码中)不是初始化,而是丢弃分配并交给你进行初始化的对象,并用单独分配和初始化的对象替换它。

为了可读性(您和其他理解代码的人),我建议将 init 与 alloc 区分开来。人们理解并期望 init 初始化其对象,但不会期望您的 init 分配其对象。