How to write init methods of a UIViewController in

2019-03-08 23:21发布

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.

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

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

6条回答
We Are One
2楼-- · 2019-03-09 00:00

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

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 nil for the nibName and bundle. You should pass up whatever was passed in.

查看更多
虎瘦雄心在
3楼-- · 2019-03-09 00:00

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.

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

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:")))
 }}
查看更多
时光不老,我们不散
4楼-- · 2019-03-09 00:01

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

var tap: UITapGestureRecognizer?

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

Hope it helps

查看更多
迷人小祖宗
5楼-- · 2019-03-09 00:12

I used:

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

Some people suggested:

convenience init(){
    self.init()
}

But this gives you an infinite loop.

查看更多
聊天终结者
6楼-- · 2019-03-09 00:14

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

class ViewController: UIViewController {
    var tap: UITapGestureRecognizer?
    convenience init(){
        self.init()
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
}
查看更多
叼着烟拽天下
7楼-- · 2019-03-09 00:25

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.

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

查看更多
登录 后发表回答