Swift Overload init() Swift Overload init() xcode xcode

Swift Overload init()


Updated Answer

class Y { }class X : Y {    var title: String?    var imageName: String?    convenience override init() {        self.init(title: nil, imageName: nil)    }    convenience init(title:String?) {        self.init(title: title, imageName: nil)    }    init(title: String?, imageName: String?) {        self.title = title        self.imageName = imageName        super.init()    }}
  • Use the most complete initializer as the designated initializer.

    In this case init(title: String?, imageName: String?) is the only initializer that sets all its properties, so it should be the designated initializer.

  • Initialize your properties before calling super.init().

    My old answer only worked because title and imageName were both var and optional.

    In Two-Phase Initialization section of The Swift Programming Language: Initialization

    Safety check 1

    A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.


Old Answer

I plugged the sample into a playground, here is how I got it to work:

class Y { }class X : Y {    var title: String?    var imageName: String?    override init() {    }    init(aTitle:String?) {        super.init()        self.title = aTitle    }    convenience init(aTitle:String?, aImageName:String?) {        self.init(aTitle: aTitle)        self.imageName = aImageName    }}
  • init(aTitle:String?, aImageName:String?) cannot call init(aTitle:) and still be a designated initializer, it must be a convenience initializer.
  • self.init must be before anything else in init(aTitle:String?, aImageName:String?).
  • initializer must be passed the parameter name self.init(aTitle) must be self.init(aTitle: aTitle).

As a side note, I removed the unneeded semicolons and put super.init() first for style reasons.

Hope that helps.


UPDATE

To follow Apple's advice, there should only be one designated, the rest should be convenience initializers. For example, if you decide init(aTitle:String?) should be the designated initializer, then the code should look like:

convenience override init() {    self.init(aTitle: nil) // A convenience initializer calls the designated initializer.}init(aTitle:String?) {    super.init() // Only the designated initializer calls super.init.    self.title = aTitle}convenience init(aTitle:String?, aImageName:String?) {    self.init(aTitle: aTitle)  // A convenience initializer calls the designated initializer.    self.imageName = aImageName}

There are times when you might want more than once designated initializer, for example, UIView, but that should be an exception, not the rule.


UPDATE 2

Classes should have one designated initializer. Convenience initializer will (eventually) call the the designated initializer.

Initialization

A class may have multiple initializers. This occurs when the initialization data can take varied forms or where certain initializers, as a matter of convenience, supply default values. In this case, one of the initialization methods is called the designated initializer, which takes the full complement of initialization parameters.

Multiple initializers

The Designated Initializer

The initializer of a class that takes the full complement of initialization parameters is usually the designated initializer. The designated initializer of a subclass must invoke the designated initializer of its superclass by sending a message to super. The convenience (or secondary) initializers—which can include init—do not call super. Instead they call (through a message to self) the initializer in the series with the next most parameters, supplying a default value for the parameter not passed into it. The final initializer in this series is the designated initializer.