Swift initializers: init, convenience init, required init

Swift OOP has some niceties and differences compared to other languages I used in the past (mainly Python and C#), for example, subclass inits may have some extra complexities like performing operations in a certain order, where first we can pass the new values first, and then (after) call the superclass initializer:

init(firstname : String, surname: String, sports: [String]){
	
	self.sports = sports
	super.init(	firstname: firstname, surname: surname)
}

StudentAthlete(firstname: "blao", surname: "blao", sports: ["blao", "blao"]) 

Using multiple inits

We can also use multiple initializers, which may vary depending on what are you trying to accomplish. As an example for a Product Order on a dummy store:

public class Product {
    
    public let siteID: Int64
    public let customerID: Int64
    public let productName: String
    
    // DESIGNATED INIT
    init(siteID: Int64, customerID: Int64, productName: String) {
        self.siteID = siteID
        self.customerID = customerID
        self.productName = productName
    }

    // CONVENIENCE INIT
    convenience init(productName: String) {
        self.init(siteID: 0, customerID: 0, productName: productName)
    }

    // REQUIRED INIT
    required init?(coder aDecoder: NSCoder) {
        //super.init(coder: aDecoder) // Uncomment this one if we happen to use IB
        fatalError("Not using Interactive Builder")
    }
}

let product1 = Product(siteID: 0, customerID: 0, productName: "Noodle bowl")
let product2 = Product(productName: "Rice bowl")

print(product1.siteID, product1.customerID, product1.productName)
print(product2.siteID, product2.customerID, product2.productName)

Designated init

Designated initializers are the primary initializers for the class. These fully initialize all properties and call an appropriate superclass initializer to continue the process up the superclass chain. It must fully initialize all properties introduced by its class before calling a superclass initializer

    init(siteID: Int64, customerID: Int64, productName: String) {
        self.siteID = siteID
        self.customerID = customerID
        self.productName = productName
    }

Convenience init

Those are not required, are secondary initializers that support our class, however, these must call a designated initializer of the same class (so the object can be fully initialized ). We must not call super from our convenience initializer, but call another initializer (convenience or designated) from the same class.

There are multiple cases where we may want to use those, for example when we want to instantiate an object but we don’t want, or can’t use all parameters. This could be anything, like we may not know the store or product details at this point, or we want to set an image but we don’t want to use a specific aspect just on initialization:

convenience init(productName: String) {
    self.init(siteID: 0, customerID: 0, productName: productName)
}

Required init

Sometimes Xcode may yell at us and require to use required init?(coder aDecoder: NSCoder). This generally happens if we create a subclass from some object, and we need to either create a new initializer or override an existing initializer. Xcode will flag this as an error, telling us that we also need to include required init?(coder aDecoder: NSCoder)

Why is this?

The decoder, NSCoder bit is related to Xcode’s Interface Builder. If we are using Storyboards, we are using the Interface Builder. Everything that we set and do in Storyboards, Xcode will then translate to code behind the scenes. We can see the code it generates via git diff, these will appear in our .xib or .nib files.

The way it translates this code is by decoding it using NSCoder. Either if we are using or not using Storyboards, we will need to tell Xcode this:

required init?(coder aDecoder: NSCoder) {
    //super.init(coder: aDecoder) // If we use Interactive Builder, uncomment. There's no other superclass, so we can't use this one.
    //fatalError("Not using IB") // If we don't use Interactive Builder, uncomment.
    }

Leave a Reply