4

I am trying to init a class with arguments in Swift. I want to be able to pass an array to the class. Something like let test = MyTestClass(data).

Code:

init(data: [CGFloat]){
    super.init(nibName: "Test", bundle: nil)
    self.data = data
}

required init?(coder decoder: NSCoder) {

    super.init(nibName: "Test", bundle: nil)
}

Error:

enter image description here

rmaddy
  • 314,917
  • 42
  • 532
  • 579
J.Doe
  • 697
  • 2
  • 16
  • 26
  • What iOS class are you trying to create your custom init on? – temp Aug 18 '17 at 14:19
  • 1
    Move `super.init(nibName:bundle:)` call to the last line inside your `init(data:)` – nayem Aug 18 '17 at 14:22
  • Still have an error in required ini, Property self.date not initialized... – J.Doe Aug 18 '17 at 14:26
  • @J.Doe as nayem mentioned your current class designated initializer is initialized first and then super class init. – Tushar Sharma Aug 18 '17 at 14:26
  • If you are new with Swift, I recommend going through [this tutorial](https://www.raywenderlich.com/119922/swift-tutorial-initialization-part-1) to know more about ___initialization in Swift___. The tutorial has a second part too. – nayem Aug 18 '17 at 14:36

2 Answers2

10

You can solve the errors by initializing data before calling super also in init(coder and call the appropriate super method in init(coder

let data : [CGFloat]

init(data: [CGFloat]){
    self.data = data
    super.init(nibName: "Test", bundle: nil)
}

required init?(coder decoder: NSCoder) {
    self.data = [CGFloat]()
    super.init(coder: decoder)
}

Alternatively declare data as

var data = [CGFloat]()

then you can write

init(data: [CGFloat]){
    self.data = data
    super.init(nibName: "Test", bundle: nil)
}

required init?(coder decoder: NSCoder) {
    super.init(coder: decoder)
}

In any case you have to call super.init(coder: decoder) in init(coder.

vadian
  • 274,689
  • 30
  • 353
  • 361
3

Swift requires all parameters to be set by the time the initialiser completes. It also requires these parameters to be set before calling another function, which is why the super initialiser is called afterwards, rather than in the first line as required by Objective-C.

In the normal initialiser, you are setting the value of data to the passed in array. But you aren't doing so for the init(coder:) method.

There are two ways to handle this:

One way is to just throw an assertion if the init(coder:) initialiser is called.

required init?(coder decoder: NSCoder) {
    fatalError("Not meant to be initialised this way")
}

The other is to assign a "empty" value:

required init?(coder decoder: NSCoder) {
    data = [CGFloat]() // just set an empty array
    super.init(nibName: "Test", bundle: nil)
}

The method you choose depends on how you want to use the code in your domain. I mostly choose the first option, because calling an initialiser that isn't meant to be used is a developer error, and it is a good idea to just crash for those types of error.

Abizern
  • 146,289
  • 39
  • 203
  • 257