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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30679129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:14:09  来源:igfitidea点击:

How to write init methods of a UIViewController in Swift

iosswiftuiviewcontrolleruikitdesignated-initializer

提问by Ankit Goel

I am unable to add init method to the following UIViewController class. I need to write some code in the init method. Do i have to write init(coder) method? Even when I add the coder and decoder methods I still get errors. I also tried using the init method without any parameters but that also does not seem to work.

我无法将 init 方法添加到以下 UIViewController 类。我需要在 init 方法中编写一些代码。我必须编写 init(coder) 方法吗?即使我添加了编码器和解码器方法,我仍然会出错。我也尝试使用不带任何参数的 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:"))
    }

...
...
}

If I call the super.init() method without parameters the error is "Must call a designated initializer of super class" and if I pass the parameter nib and bundle then error is "Required initializer init(coder)".

如果我不带参数调用 super.init() 方法,则错误是“必须调用超类的指定初始化程序”,如果我传递参数 nib 和 bundle,则错误是“必需的初始化程序 init(coder)”。

Even when I add init(coder) and init(decoder) it does not work.

即使我添加 init(coder) 和 init(decoder) 它也不起作用。

回答by Glauco Neves

I used:

我用了:

convenience init() {
    self.init(nibName:nil, bundle:nil)
}

Some people suggested:

有人建议:

convenience init(){
    self.init()
}

But this gives you an infinite loop.

但这给了你一个无限循环。

回答by Jamie Birch

All of these answers are half-answers. Some people are experiencing infinite loops in related posts because they are only adding the convenience init()(it recursively calls itself if you don't providing a distinct init()method for it to invoke), while other people are neglecting to extend the superclass. This format combines all the solutions to satisfy the problem completely.

所有这些答案都是一半的答案。有些人在相关帖子中遇到无限循环,因为他们只添加了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
}

Edit:Also, if you want to initialise any class properties using parameters passed into your convenience init()method without all the overridden init()methods complaining, then you may set all those properties as implicitly unwrapped optionals, which is a pattern used by Apple themselves.

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

回答by Aaron Rasmussen

You need to override the init(nibName:bundle:)initializer, andprovide the init(coder:)required initializer, and initialize tapin both of them:

您需要覆盖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:"))
    }
...
...
}

Also, be sure when calling the superclass initializer that you don't just pass nilfor the nibNameand bundle. You should pass up whatever was passed in.

此外,父类的初始化,你不只是传递时一定nilnibNamebundle。你应该放弃传递的任何东西。



Note that the "convenience init" methodmentioned in some answers is only relevant if you are actually "by hand" yourself initializing a view controller. (There are very few situations where you would do that.) If you want to "do something during normal initialization"- so for example create a gesture recognizer or just initialize some variables - the only possible solution is exactly the one given in this answer.

请注意,某些答案中提到的“convenience init”方法仅在您实际“手动”初始化视图控制器时才相关。(很少有您会这样做的情况。)如果您想“在正常初始化期间做某事”-例如创建手势识别器或仅初始化一些变量-唯一可能的解决方案正是此答案中给出的解决方案.

回答by Icaro

You can just create a convenience initializer instead, convenience initializers don't override the init() instead it just calls it making things easier.

您可以只创建一个便利初始值设定项,便利初始值设定项不会覆盖 init() 而只是调用它使事情变得更容易。

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

回答by Ashish Kakkad

I think you have to add

我想你必须添加

required init(coder aDecoder: NSCoder) {
    print("init coder")
    super.init(coder: aDecoder)
}

or

或者

convenience init() {
    self.init()
}

You have to write init too. Don't remove it

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

var tap: UITapGestureRecognizer?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
    super.init(nibName: nil, bundle: nil)
}

Hope it helps

希望能帮助到你

回答by Vinod Supnekar

I came across this Question of You asked long way Back. But no one has provided a basic answer to the question. It's a basic in Swift that:- Subclass must initialize its variables before it's super class initialization is complete.

我遇到了这个你问很久的问题。但是没有人对这个问题给出基本的答案。这是 Swift 中的一个基本原则:- 子类必须在其超类初始化完成之前初始化其变量。

Hence as Ankit Goelmentioned the crash :- "Must call a designated initializer of superclass"

因此,正如Ankit Goel提到的崩溃:-“必须调用超类的指定初始值设定项”

Hence updated code would be:-

因此更新的代码将是:-

class ViewController: UIViewController {
 var tap: UITapGestureRecognizer?

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

required init?(coder aDecoder: NSCoder) {
print("init coder style")
self.tap = nil
super.init(coder: aDecoder)
tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))
 }}