1

I'm new to Swift, coming from web dev, so I am quite used to components. I am trying to create a form, and would like to reuse the textfield and label in other Views. I have created a new class that inherence from UIView, and want to override the init to create set new properties.

My code so far

final class TextFormField: UIView {
    var labelText: String
    var secureText: Bool
    var keyboardType: UIKeyboardType

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    init(labelText: String, secureText: Bool, keyboardType: UIKeyboardType){
        self.labelText = labelText
        self.secureText = secureText
        self.keyboardType = keyboardType
        super.init()
    }
    convenience init() {
        self.init()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

The error I get now is Must call a designated initializer of the superclass 'UIView' on the second init.

How can I override the init to take 3 more parameters? Do I need to do an extension instead?

Thanks in advance

Sebastian Berglönn
  • 3,920
  • 2
  • 17
  • 33
  • Possible duplicate of [Build error when trying to override an initializer in Xcode 6.3 Beta 3](https://stackoverflow.com/questions/29068534/build-error-when-trying-to-override-an-initializer-in-xcode-6-3-beta-3) – Rakesha Shastri Nov 29 '18 at 09:14
  • Just remove your `convenience init`. – LinusGeffarth Nov 29 '18 at 09:14
  • @LinusGeffarth I have the same error as before after removing the `convenience init` – Sebastian Berglönn Nov 29 '18 at 09:15
  • 1
    What if you replace `super.init()` with `super.init(frame: .zero)`? – LinusGeffarth Nov 29 '18 at 09:16
  • that solved that issue! Now I get `Property 'self.labelText' not initialized at super.init call` inside the `override init`. Do I have to add those properties there? @LinusGeffarth – Sebastian Berglönn Nov 29 '18 at 09:17
  • The thing is that those variables are not initialized when the `init(frame: CGRect)` method is used. You could either assign them a default value, make them implicitly unwrapped or call another initializer method before calling `super.init(frame: frame)`. – LinusGeffarth Nov 29 '18 at 09:18

2 Answers2

2

You should get rid of all unnecessary initialisers and make sure that your custom init method calls one of the designated initialisers of super.

final class TextFormField: UIView {
    var labelText: String
    var secureText: Bool
    var keyboardType: UIKeyboardType

    init(labelText: String, secureText: Bool, keyboardType: UIKeyboardType){
        self.labelText = labelText
        self.secureText = secureText
        self.keyboardType = keyboardType
        super.init(frame: .zero)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
2

There are two issues in your code preventing it from compiling:

Missing initializers

The override init(frame: CGRect) does not initialize the variables you've declared (labelText, secureText, keyboardType).
To resolve this, you have the following options:

  1. add default values:

    var labelText: String = ""
    
  2. make the variables implicitly unwrapped - note that the variables may be nil when not initialized before usage

    var labelText: String!
    
  3. omit the override init(frame: CGRect) method as you're not using it. That'll also allow you to keep your current variable declarations.

Wrong initializer call

In init(labelText: String, secureText: Bool, keyboardType: UIKeyboardType), you need to call a super-initializer.
To do so, replace:

super.init()

with:

super.init(frame: .zero)
LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174