为什么我不能在Swift中的UIViewController上调用默认的super.init()?

Sir*_*III 70 objective-c uiviewcontroller ios swift ios8

我没有使用UIViewController故事板中的一个,我希望有一个自定义init函数,我传入NSManagedObjectID一些对象.我只想像super.init()在Objective-C中一样打电话.像这样:

init(objectId: NSManagedObjectID) {
    super.init()
}
Run Code Online (Sandbox Code Playgroud)

但是我得到以下编译器错误:

必须调用超类UIViewController的指定初始值设定项

我可以不再这样做了吗?

occ*_*lus 105

对于指定的初始化器UIViewControllerinitWithNibName:bundle:.你应该打电话给那个.

http://www.bignerdranch.com/blog/real-iphone-crap-2-initwithnibnamebundle-is-the-designated-initializer-of-uiviewcontroller/

如果您没有nib,请传入nilnibName(bundle也是可选的).然后,您可以构建自定义视图,loadView或者通过将子视图添加到self.viewin中viewDidLoad,与以前一样.

  • 所以我目前不可能在不是来自nib的UIViewController子类中创建自定义init方法? (3认同)
  • 谢谢!对于快速复制/粘贴,只需在设置您的`let`属性(如果有)后调用此函数:`super.init(nibName:nil,bundle:nil)`。 (3认同)
  • 呵呵,挖了一点,原来`initWithCoder:`来自`NSCoding`协议……还是搞不清楚它在初始化一个UIViewController实例时的作用是什么,是否是UIViewController的“指定”初始化器或者它的任何超类... (2认同)
  • Init With编码器用于需要进行状态还原的情况。使用状态恢复功能保存视图控制器的状态时,编码器将返回保存状态时保存的值。从那里,您可以在关闭应用程序后将视图控制器重建到其最后的初始状态。所以对于用户来说,他们离开的地方 (2认同)

Kla*_*aas 39

另一个不错的解决方案是将新的初始化程序声明为convenience初始化程序,如下所示:

convenience init( objectId : NSManagedObjectID ) {
    self.init()

    // ... store or user your objectId
}
Run Code Online (Sandbox Code Playgroud)

如果您在子类中根本没有声明指定的初始值设定项,它们将自动继承,您可以self.init()在便利初始化程序中使用它们.

在UIViewController中的情况下,默认的init()方法将调用init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!)具有nil两个参数(命令点击UIViewController中会给你的信息).

TL; TR:如果您更喜欢以编程方式使用UIViewControllers,这是一个完整的工作示例,它添加了一个带有自定义参数的新初始化程序:

class MyCustomViewController: UIViewController {
    var myString: String = ""

    convenience init( myString: String ) {
        self.init()

        self.myString = myString
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案的"诀窍"是`myString`被设置为``"`所以`init`不是必需的.如果你不想使用初始值,这个解决方案就会崩溃,在这种情况下你需要使用`self.init(nibName:nil,bundle:nil)` (7认同)
  • 我尝试在扩展中执行此操作,并以递归方式调用自身. (2认同)
  • @Yar或你使`myString`属性成为可选项 (2认同)

NcN*_*cNc 11

更新:添加链接

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init

根据iOS的文档,UIViewController的指定初始化程序是initWithNibName: bundle:.

如果您是UIViewController的子类,则必须调用此方法的超级实现,即使您没有使用NIB也是如此.

你可以这样做:

init(objectId : NSManagedObjectID) {

    super.init(nibName: (xib's name or nil'), bundle: nil)

   // other code...
}
Run Code Online (Sandbox Code Playgroud)

要么

声明一个新的初始化器作为便利初始化器:

 convenience init( objectId : NSManagedObjectID ) {

    self.init()

     // other code...
Run Code Online (Sandbox Code Playgroud)

}

  • @mykolaj:信息*已经*在这里,在这个答案中。(否则我会标记为仅删除链接的答案。)但是归属也很重要,这样任何阅读此内容的人都可以找出它的来源并归功于他们。屏幕截图对此不起作用,但链接可以。如果一个链接失效了,那是不幸的,但你不可能告诉我这比根本没有任何形式的信用更糟糕。SO 对仅链接答案的反对意见是仅链接**答案。不链接。链接*以及*信息是所需的表述。 (2认同)

Vya*_*lav 9

为了改善occulus的答案:

init() {
     super.init(nibName: nil, bundle: nil)
}
Run Code Online (Sandbox Code Playgroud)