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


84

我不是UIViewController从情节提要中使用a ,而是要有一个自定义init函数,可以在其中传递NSManagedObjectID某些对象的。我只想像super.init()在Objective-C中一样打电话。像这样:

init(objectId: NSManagedObjectID) {
    super.init()
}

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

必须调用超类UIViewController的指定初始化程序

我可以不再这样做吗?

Answers:


119

对于指定的初始化器UIViewControllerinitWithNibName:bundle:。您应该打电话给它。

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

如果您没有笔尖,请nil输入nibName(捆绑包也是可选的)。然后,你可以在构建自定义视图loadView或通过添加子视图self.viewviewDidLoad,你一样使用。


4
因此,对于我来说,当前不可能在不是来自笔尖的UIViewController子类中创建自定义init方法吗?
SirRupertIII

1
啊,谢谢!我输入的笔尖名称是“”。
SirRupertIII

2
呵呵,经过一番挖掘,结果发现initWithCoder:它来自NSCoding协议...我仍然不知道它在初始化UIViewController实例中起什么作用,无论它是UIViewController的“指定”初始化器还是其任何超类。 。
萨科Miari

6
谢谢!要进行快速复制/粘贴,只需在设置let属性(如果有)后调用此按钮:super.init(nibName: nil, bundle: nil)
Ferran Maylinch '17

3
Init With编码器用于需要状态恢复的情况。使用状态还原功能保存视图控制器的状态时,编码器将返回保存状态时保存的值。从那里,您可以在关闭应用程序后将视图控制器重建到其最后的初始状态。因此,对于用户来说,他们离开的地方
Esko918

44

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

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

    // ... store or user your objectId
}

如果您在子类中根本没有声明任何指定的初始值设定项,则它们将被自动继承,并且可以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
    }
}

这是一种更优雅的解决方案,并且适用于任何通用情况
Ciprian

2
我尝试在扩展中执行此操作,并且它以递归方式调用了它自己。
Danyal Aytekin

12
此答案的“技巧”myString已设置为,""因此init不需要。如果您不想使用初始值,则此解决方案会分崩离析,在这种情况下,您需要使用self.init(nibName: nil, bundle:nil)
Dan Rosenstark 2015年

2
@Yar或者您做出myString财产可选
克拉斯

1
@Klaas是的:我的问题是我仅在使用初始化程序来避免使用可选内容,并使我的代码得以编译。
Dan Rosenstark 2015年


15

更新:添加链接

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...
}

要么

声明一个新的初始化程序作为便捷的初始化程序:

 convenience init( objectId : NSManagedObjectID ) {

    self.init()

     // other code...

}


1
您应该链接到原始内容以进行署名,而不是将其保留为大屏幕截图。
内森·塔吉

我使用了与@NcNc相同的过程。它为我工作。这里的链接
阿尼尔·古普塔

@NathanTuggy不,他不应该。链接具有终止或移动某天的功能。谁想看到404错误而不是他/她正在寻找的信息?
mykolaj

1
@mykolaj:此答案中的信息已经在这里。(否则,我会一直将删除标记为仅链接的答案。)但是归因也很重要,这样任何阅读此内容的人都可以找出它的来源并将其归功于他们。屏幕截图不适用于此功能,但链接可以。如果链接腐烂了,那很不幸,但是您可能无法告诉我,这比没有任何形式的信誉来得糟糕。SO所反对的仅链接答案就是链接答案。不链接。链接以及信息是所需的公式。
内森·塔吉

@NathanTuggy我刚刚添加了链接。感谢您的提醒
-NcNc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.