Swift init: The useful explanation you need to know

Continuing the series of articles about Swift is Swift init. And, are you interested in swift init but do not fully understand it? Then, let’s follow the article below of ArrowHiTech. Following that, this blog not only gives you the most overview of Swift init, but also provides you with the most useful explanations for your Swift init process. Then, what are you waiting for without reading it right now!

A little reminder about Swift

Firstly, Swift is one of the latest and popular programming languages manufactured in the market. Besides, it has been manufactured since 2014 by the biggest technology company – Apple Inc. This language is fully compatible with applications of Apple such as: iOS, macOS, watchOS and tvOS. What’s more, Swift is a general-purpose, multi-paradigm, object-oriented, functional, imperative and block structured language

In reality, swift was created with the mission to resolve many existing problems of Objective C. During the period from 2014 until now, it has many improvements from version calls 1.0, 2.0, 3.0 and 4.0 and later. 

The reasons to choose Swift

Firstly, Fast development process

Besides, it highly ensures security and performance

Thirdly, it has great interactivity with Objective – C

Fourthly, automatic memory management

What is Swift init? 

In fact, Swift init, in general, are as similar as constructors in java programming. And, Swift includes a number of constraints for initializers because it is a type-safe language. So, if you don’t understand the notion in detail, it can be difficult to put into practice.

How about Swift init() syntax?

Now, coming to the Swift init() syntax:

init() {

    // initialise the stored properties here.

}

Then, let’s have a look at the following example class:

class A{

    //Compilation error. No initializer is defined.

    var a : Int

    var b : String

    var c : Int?

    let website = “JournalDev”

}

Firstly, the code in the preceding class will not compile. Besides, the saved properties aren’t initialized, according to the swift compiler. Moreover, it’s impossible to keep Stored Properties in an undefined state. 

As a result, Swift init will bring us two possible choices. Then, which are they? After that, you should refer to them below:

#1. Firstly, in the property definition, set a default property value.

So, let’s explore the first way:

class A{

    var a : Int = 5

    var b : String = “Hello. How you’re doing”

    var c : Int?

    let website = “JournalDev”

}

To begin, because we’ve provided a default value for each of the stored attributes, Swift init automatically supplies us with the default initializer. Once the class has been initialized, the dot operator can be used to access all of the properties and functions.

var object = A()

object.a = 10

object.c = 2

#2. Secondly, to initialize the properties, use the init() initializer.

In particular, the second option is to use the init() method to initialize the saved properties, as illustrated below. So, let’s see now:

class A{

    var a : Int

    var b : String

    var c : Int?

    let website = “JournalDev”

    init(a: Int, b: String) {

        self.a = a

        self.b = b

    }

}

var object = A(a: 5, b: “Hello World”)

In reality, Swift Optional isn’t a saved property, so keep that in mind. As a result, don’t have to be initialized. Besides, the self property is used to access stored properties within the init() method.

What’s more, you should note that within its own instance methods, self is used to refer to the current instance (Same as this in java). Also, the above initializer is the class’s principal initializer. Besides, it’s sometimes referred to as the designated initializer.

Moreover, Swift init also allows us to change a constant property.

class A{

    var a : Int

    var b : String

    var c : Int?

    let website : String

    init(a: Int, b: String, website: String) {

        self.a = a

        self.b = b

        self.website = website

    }

}

var object = A(a: 5,b: “Hello World”, website: “JournalDev”)

Memberwise Swift Initializers for Structures

Now, let’s take a look at the code snippets below and you will surely understand how to initialize a struct:

struct Rect{

    var length : Int

    var breadth : Int

}

var r = Rect(length: 5, breadth: 10)

struct Rect{

    var length : Int = 5

    var breadth : Int = 10

}

var r = Rect()

var r1 = Rect(length: 10, breadth: 5)

Firstly, as you can see, we get a default initializer without member initialization along with the memberwise initializer. And, this is because we set default values to the stored properties in the above sample.

struct Rect{

    var length : Int

    var breadth : Int

    init(length: Int, breadth: Int) {

        self.length =  length + 10

        self.breadth = breadth + 10

    }

}

var r = Rect(length: 10, breadth: 5)

How to use Parameters without External Name?

Specifically, when an initializer Swift init does not require an external name, the underscore ‘_’ is used to denote the same, as seen below. Then, let’s take a look now!

class A{

    var a : Int

    var b : String

    var c : Int?

    let website = “JournalDev”

    init(_ a: Int, _ b: String) {

        self.a = a

        self.b = b

    }

}

var object = A(5,”Hello World”)

struct Rect{

    var length : Int

    var breadth : Int

    init(_ length: Int, _ breadth: Int) {

        self.length =  length + 10

        self.breadth = breadth + 10

    }

}

var r = Rect(10, 10)

Swift Init Types

In fact, the following sorts of initializers for classes can be roughly classified:

#1. Firstly, Designated Initializers

#2. Secondly, Convenience Initializers

class Student{

    var name : String

    var degree : String

    init(name : String, degree: String) {

        self.name = name

        self.degree = degree

    }

    convenience init()

    {

        self.init(name: “Unnamed”, degree: “Computer Science”)

    }

}

var student = Student()

student.degree // “Computer Science”

student.name // “Unnamed”

Delegation of Swift Initializers for Value Types

In fact, it is possible to invoke an initializer from another, reducing duplication of code, and reducing duplication of code as a result. Besides, Inheritance is not supported by Value Types like Structures. Therefore, the only option is to call the initializer from within the same structure. Then, let’s keep your eyes with the instance below:

struct Rect{

    var length : Int

    var breadth : Int

    init(_ length: Int, _ breadth: Int) {

        self.length =  length

        self.breadth = breadth

    }

    init(_ length: Int)

    {

        self.init(length, length)

    }

}

var r = Rect(10, 5)

var r1 = Rect(15) //initialises the length and breadth to 15

Delegation of Swift Initializers for Reference Types

For more details, the following illustration will describe the main rules for dealing with initializer relationships in detail. Then, let’s explore: 

swift init

Inheritance and Overriding of Swift Init

Firstly, unless specific criteria are met, Swift Init subclasses do not inherit their superclass’s initializers by default. In fact, this is done to avoid the subclass having a half-baked initialization.

Then, in order to understand it according to the simple way, let’s refer to the following example:

enum VehicleType : String {

    case twoWheeler = “TwoWheeler”

    case fourWheeler = “FourWheeler”

}

class Vehicle{

    var vehicleType : VehicleType

    init(vehicleType: VehicleType) {

        self.vehicleType = vehicleType

        print(“Class Vehicle. vehicleType is \(self.vehicleType.rawValue)\n”)

    }

    convenience init()

    {

        self.init(vehicleType: .fourWheeler)

    }

}

var v = Vehicle(vehicleType: .twoWheeler)

Then, as illustrated below, we’ll create a subclass of the aforesaid class. So, let’s explore below:

enum TwoWheelerType : String

{

    case scooty = “Scooty”

    case bike = “Bike”

}

class TwoWheeler : Vehicle{

    var twoWheelerType : TwoWheelerType

    var manufacturer : String

    init(twoWheelerType : TwoWheelerType, manufacturer : String, vType : VehicleType) {

        self.twoWheelerType = twoWheelerType

        self.manufacturer = manufacturer

        print(“Class TwoWheeler. \(self.twoWheelerType.rawValue) manufacturer is \(self.manufacturer)”)

        super.init(vehicleType: vType)

    }

}

The result

And, a compile-time error would result from the following code:

class TwoWheeler : Vehicle{

    var twoWheelerType : TwoWheelerType

    var manufacturer : String

    init(twoWheelerType : TwoWheelerType, manufacturer : String, vType : VehicleType) {

        self.twoWheelerType = twoWheelerType

        self.manufacturer = manufacturer

        self.vehicleType = vType //Won’t compile

        super.init(vehicleType: vType)

        //self.vehicleType = .fourWheeler //This would work.

    }

}

var t = TwoWheeler(twoWheelerType: .scooty, manufacturer: “Hero Honda”, vType: .twoWheeler)

As previously stated, the superclass initializer is not immediately inherited by the subclass.

As a result, the startup below would fail

var t = TwoWheeler(vehicleType: .twoWheeler) //manufacturer property isn’t initialized.

Next, the subclass initializer must be the same as the superclass’s predefined initializer in order to override an initializer. Then, in this scenario, the initializer has the override keyword added to it.

class TwoWheeler : Vehicle{

    var twoWheelerType : TwoWheelerType

    var manufacturer : String

    init(twoWheelerType : TwoWheelerType, manufacturer : String, vType : VehicleType) {

        self.twoWheelerType = twoWheelerType

        self.manufacturer = manufacturer

        print(“Class TwoWheeler. \(self.twoWheelerType.rawValue) manufacturer is \(self.manufacturer)”)

        super.init(vehicleType: vType)

    }

    override init(vehicleType: VehicleType)

    {

        print(“Class TwoWheeler. Overriden Initializer. \(vehicleType.rawValue)”)

        self.twoWheelerType = .bike

        self.manufacturer = “Not defined”

        super.init(vehicleType: vehicleType)

    }

Besides, because the parameter names are different, the initializer below does not override the one from the superclass

//This would give a compile-time error since the parameter v doesn’t match with the superclass.

override init(v: VehicleType)

    {

        self.twoWheelerType = .bike

        self.manufacturer = “Not defined”

        super.init(vehicleType: v)

    }

Using Convenience Initializer

Specifically, to override the one from superclass, you can use Convenience Initializer. Then, let’s refer to below:

class TwoWheeler : Vehicle{

    var twoWheelerType : TwoWheelerType

    var manufacturer : String

    init(twoWheelerType : TwoWheelerType, manufacturer : String, vType : VehicleType) {

        self.twoWheelerType = twoWheelerType

        self.manufacturer = manufacturer

        print(“Class TwoWheeler. \(self.twoWheelerType.rawValue) manufacturer is \(self.manufacturer)”)

        super.init(vehicleType: vType)

    }

    override convenience init(vehicleType: VehicleType) {

        self.init(twoWheelerType: .bike, manufacturer: “Not Defined”, vType: .twoWheeler)

        self.vehicleType = vehicleType

    }

}

var t = TwoWheeler(twoWheelerType: .scooty, manufacturer: “Hero Honda”, vType: .twoWheeler)

t = TwoWheeler(vehicleType: .twoWheeler)

//Output

Following gets printed on the console:

Firstly, Class TwoWheeler. Scooty manufacturer is Hero Honda

Secondly, Class Vehicle. vehicleType is TwoWheeler

Thirdly, Class TwoWheeler. Bike manufacturer is Not Defined

Lastly, Class Vehicle. vehicleType is TwoWheeler

Required Initializers

Firstly, look at the illustrated example below: 

class Vehicle{

    var vehicleType : VehicleType

    required init(vehicleType: VehicleType) {

        self.vehicleType = vehicleType

        print(“Class Vehicle. vehicleType is \(self.vehicleType.rawValue)\n”)

    }

    convenience init()

    {

        self.init(vehicleType: .fourWheeler)

    }

}

class TwoWheeler : Vehicle{

    var twoWheelerType : TwoWheelerType

    var manufacturer : String

    init(twoWheelerType : TwoWheelerType, manufacturer : String, vType : VehicleType) {

        self.twoWheelerType = twoWheelerType

        self.manufacturer = manufacturer

        print(“Class TwoWheeler. \(self.twoWheelerType.rawValue) manufacturer is \(self.manufacturer)”)

        super.init(vehicleType: vType)

    }

     required init(vehicleType: VehicleType) {

        self.manufacturer = “Not Defined”

        self.twoWheelerType = .bike

        super.init(vehicleType: vehicleType)

    }

}

Making use of a Required Initializer with Convenience

In fact, the required and convenience initializers are not mutually exclusive and can be combined. And, let’s explore the following example about this Swift init:

enum FourWheelerType : String

{

    case car = “Car”

    case bus = “Bus”

    case truck = “Truck”

}

class FourWheeler : Vehicle

{

    var fourWheelerType : FourWheelerType

    var name : String

    init(fourWheelerType : FourWheelerType, name: String, vehicleType: VehicleType) {

        self.fourWheelerType = fourWheelerType

        self.name = name

        print(“Class FourWheeler. \(self.fourWheelerType.rawValue) Model is \(self.name)”)

        super.init(vehicleType: vehicleType)

        self.vehicleType = vehicleType

    }

    required convenience init(vehicleType: VehicleType) {

        self.init(fourWheelerType: .bus, name: “Mercedes”, vehicleType: vehicleType)

    }

}

class Car : FourWheeler{

    var model : String

    init(model: String) {

        self.model = model

        print(“Class Car. Model is \(self.model)”)

        super.init(fourWheelerType: .car, name: self.model, vehicleType: .fourWheeler)

    }

    required init(vehicleType: VehicleType)

    {

        self.model = “Not defined”

        print(“Class Car. Model is \(self.model)”)

        super.init(fourWheelerType: .car, name: self.model, vehicleType: vehicleType)

    }

}

Automatic Initializer Inheritance

Firstly, there are two situations in which a subclass Swift init inherits the superclass’s initializers automatically. So, let’s refer to each curriculum:

At first, the first situation is:

class Name {

    var name: String

    init(n: String) {

        self.name = n

    }

}

class Tutorial: Name {

    var tutorial : String? = “Swift Initialization”

}

var parentObject = Name(n: “Anupam”)

var childObject = Tutorial(n: “JournalDev”)

Then, let’s keep an eye at the second scenario below:

class Name {

    var name: String

    init(n: String) {

        self.name = n

    }

    convenience init()

    {

        self.init(n: “No name assigned”)

    }

}

class Tutorial: Name {

    var tutorial : String? = “Swift Tutorial”

    override init(n : String) {

        super.init(n: n)

    }

}

var parentObject = Name(n: “Anupam”)

var childObject = Tutorial(n: “JournalDev”)

var childObject2 = Tutorial()

print(childObject2.name) //prints “No name assigned

Swift Failable Initializer

#1. Firstly, Failable Swift Init With Structures

struct SName {

    let name: String

    init?(name: String) {

        if name.isEmpty { return nil }

        self.name = name

    }

}

var name = SName(name: “JournalDev”)

if name != nil {

    print(“init success”) //this gets displayed

}

else{

    print(“init failed”)

}

name  = SName(name: “”)

if name != nil {

    print(“init success”)

}

else{

    print(“init failed”) //this gets displayed

}

#2. Secondly, Failable Swift Init With Enums

enum CharacterExists {

    case A, B

    init?(symbol: Character) {

        switch symbol {

        case “A”:

            self = .A

        case “B”:

            self = .B

        default:

            return nil

        }

    }

}

let ch = CharacterExists(symbol: “C”)

if ch != nil {

    print(“Init failed. Character doesn’t exist”)

}

Overriding a Failable Swift Init

Firstly, you should the lines of code below. In fact, below is an example of overriding a failable Swift init with a non-failable initializer:

class CName {

    let name: String

    init?(name: String) {

        if name.isEmpty { return nil }

        self.name = name

    }

}

var name  = CName(name: “”)

class SubName : CName{

    var age : Int

    override init(name: String)

    {

        self.age = 23

        super.init(name: name)!  

    }

}

In conclusion

As you know, Swift init is one of the most important parts for iOS app development. In fact, those are useful explanations ArrowHiTech brings to you. Thus, you can easily refer to and apply it for your business effectively. However, Swift also includes many other amazing features you need to know such as: Swift function, Swift Array and so much more.

Above all, ArrowHiTech hopes through this blog, you will easily gain further information about the topic of Swift init. Besides, during the using process of Swift init, if you face any difficult issue, let’s ArrowHiTech know. Then, with a lot of experiences in Swift and Objective-C IOS App Development Services, we are always ready to help you resolve them quickly. 

Tags

Share