【问题标题】:Why can't I call the default super.init() on UIViewController in Swift?为什么我不能在 Swift 中调用 UIViewController 上的默认 super.init()?
【发布时间】:2014-06-07 07:48:11
【问题描述】:

我没有使用情节提要中的UIViewController,我希望有一个自定义的init 函数,我在其中传入某个对象的NSManagedObjectID。我只想像在 Objective-C 中一样调用super.init()。像这样:

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

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

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

我可以不再这样做了吗?

【问题讨论】:

    标签: ios objective-c uiviewcontroller swift ios8


    【解决方案1】:

    UIViewController 的指定初始化程序是 initWithNibName:bundle:。您应该改为调用它。

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

    如果您没有 nib,请传入 nil 作为 nibName(bundle 也是可选的)。然后你可以在loadView 中构造一个自定义视图,或者通过在viewDidLoad 中向self.view 添加子视图,就像你以前一样。

    【讨论】:

    • 所以我目前不可能在不是来自 nib 的 UIViewController 子类中创建自定义 init 方法?
    • 啊,谢谢!!我正在传递“”作为笔尖名称。
    • 哦,经过一番挖掘,原来initWithCoder:来自NSCoding协议...我还是想不通它在初始化一个UIViewController实例中的作用,到底是不是UIViewController 或其任何超类的“指定”初始化程序...
    • 谢谢!要快速复制/粘贴,只需在设置 let 属性后调用此函数(如果有):super.init(nibName: nil, bundle: nil)
    • Init With coder 用于需要进行状态恢复的时候。当您使用状态恢复功能保存视图控制器的状态时,编码器将返回您在保存状态时保存的值。从那里您可以将视图控制器重建到关闭应用程序时的最后一个初始状态。所以对用户来说,这是他们离开的地方
    【解决方案2】:

    另一个不错的解决方案是将您的新初始化程序声明为 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 上的 Command-Click 将为您提供该信息)。

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

    class MyCustomViewController: UIViewController {
        var myString: String = ""
    
        convenience init( myString: String ) {
            self.init()
    
            self.myString = myString
        }
    }
    

    【讨论】:

    • 这是一个更优雅的解决方案,适用于任何一般情况
    • 我尝试在扩展中这样做,它递归地调用了自己。
    • 这个答案的“诀窍”是myString 设置为"",因此不需要init。如果您不想使用初始值,此解决方案将失效,在这种情况下您需要使用 self.init(nibName: nil, bundle:nil)
    • @Yar 或者您将 myString 属性设为可选
    • @Klaas 是的:我的问题是我使用初始化程序只是为了避免使用选项并让我的代码编译。
    【解决方案3】:

    要改进 Oculus 的 答案:

    init() {
         super.init(nibName: nil, bundle: nil)
    }
    

    【讨论】:

      【解决方案4】:

      更新:添加链接

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

      }

      【讨论】:

      • 您应该链接到原件以进行署名,而不是将其保留为屏幕截图。
      • 我使用了与@NcNc 说的相同的过程。它对我有用。这是link
      • @NathanTuggy 不,他不应该。链接具有某天到期或移动的功能。谁希望看到 404 错误而不是他/她正在寻找的信息?
      • @mykolaj:信息已经在这里,在这个答案中。 (否则我会将删除标记为仅链接的答案。)但是归因也很重要,因此任何阅读此内容的人都可以找出它的来源并归功于他们。屏幕截图不适用于此,但链接可以。如果链接失效,那很不幸,但你不可能告诉我这比根本没有任何信用更糟糕的情况。 SO对仅链接答案的反对意见是对链接-答案。不要链接。链接以及信息是所需的公式。
      • @NathanTuggy 我刚刚添加了链接。感谢您的提醒
      猜你喜欢
      • 2014-11-07
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      相关资源
      最近更新 更多