如何在Swift中编写UIViewController的init方法

Ank*_*oel 48 uiviewcontroller uikit designated-initializer ios swift

我无法将init方法添加到以下UIViewController类.我需要在init方法中编写一些代码.我必须编写init(编码器)方法吗?即使我添加编码器和解码器方法,我仍然会遇到错误.我也尝试使用没有任何参数的init方法,但这似乎也不起作用.

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
        super.init(nibName: nil, bundle: nil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

...
...
}
Run Code Online (Sandbox Code Playgroud)

如果我调用不带参数的super.init()方法,则错误为"必须调用超类的指定初始化程序",如果我传递参数nib和bundle,则错误为"必需的初始化程序初始化程序(编码器)".

即使我添加init(编码器)和init(解码器)它也不起作用.

Gla*_*ves 62

我用了:

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

有人建议:

convenience init(){
    self.init()
}
Run Code Online (Sandbox Code Playgroud)

但这会给你一个无限循环.

  • 不会被我的控制器调用。 (4认同)

Jam*_*rch 32

所有这些答案都是半答案.有些人在相关帖子中遇到无限循环,因为他们只是添加convenience init()(如果你没有提供一个独特的init()方法来调用它会递归调用自己),而其他人则忽略了扩展超类.此格式结合了所有解决方案以完全满足问题.

// This allows you to initialise your custom UIViewController without a nib or bundle.
convenience init() {
    self.init(nibName:nil, bundle:nil)
}

// This extends the superclass.
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
}

// This is also necessary when extending the superclass.
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented") // or see Roman Sausarnes's answer
}
Run Code Online (Sandbox Code Playgroud)

编辑:另外,如果你想使用传递给你的convenience init()方法的参数初始化任何类属性而没有所有被覆盖的init()方法抱怨,那么你可以将所有这些属性设置为隐式解包的选项,这是Apple自己使用的模式.

  • 这个答案是 100% 错误的:) 你***不需要***需要方便的初始化程序。(1) 如果您的目标是添加更多初始化(即早于 viewDidLoad),您需要两个 init(而不是方便的 init)。(2) 如果您的目标是手动初始化视图控制器(出于某种奇怪的原因),那么您需要方便的 init (而不是其他两个)。任何读到这个答案的新手都会完全误解发生了什么。 (2认同)

Aar*_*sen 21

您需要覆盖init(nibName:bundle:)初始化程序,提供init(coder:)所需的初始化程序,并tap在其中初始化:

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
        print("init nibName style")
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

    // note slightly new syntax for 2017
    required init?(coder aDecoder: NSCoder) {
        print("init coder style")
        super.init(coder: aDecoder)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
...
...
}
Run Code Online (Sandbox Code Playgroud)

此外,请确保在调用超类初始化程序时,您不仅仅是传递nilnibNamebundle.你应该放弃传入的内容.

  • 在`required init(coder aDecoder:NSCoder)`里面,你有`super.init()`...不应该是`super.init(coder:aDecoder)`? (2认同)
  • @joliejuly “初始化水龙头”位于两个 init 中,因为 init 是互斥的,其中一个或另一个被调用,而不是两者都被调用。也就是说,这是重复的代码,应该提取到由两个公共 init 调用的私有函数(例如 private func commonInit() )中。 (2认同)

Ica*_*aro 7

您可以只创建一个便利初始化程序,方便初始化程序不会覆盖init(),而只是调用它使事情变得更容易.

class ViewController: UIViewController {
    var tap: UITapGestureRecognizer?
    convenience init(){
        self.init()
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不应该是`super.init()`? (4认同)

Ash*_*kad 6

我想你必须添加

required init(coder aDecoder: NSCoder) {
    print("init coder")
    super.init(coder: aDecoder)
}
Run Code Online (Sandbox Code Playgroud)

或者

convenience init() {
    self.init()
}
Run Code Online (Sandbox Code Playgroud)

你也必须写init。不要删除它

var tap: UITapGestureRecognizer?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
    super.init(nibName: nil, bundle: nil)
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你

  • 这给出了错误“必须调用超类的指定初始值设定项” (3认同)

归档时间:

查看次数:

71815 次

最近记录:

6 年,1 月 前