Top 10 iOS Interview Questions on Initializer in Swift

Top 10 iOS Interview Questions on Initializer in Swift
Top iOS Interview Questions on Initialiser in Swift - Swift Anytime

Q1. What is a default initializer in Swift?

A default initializer is an automatically generated constructor provided by the Swift compiler for your custom data types, such as classes and structures (structs). It allows instances of your types to be created without explicitly defining an initializer.

Q2. What is a memberwise initializer in Swift?

A memberwise initializer is an automatically generated constructor for a struct that allows you to initialize its properties by simply providing values for those properties during instance creation. It's a convenient feature to simplify the process of creating instances of a struct with named properties.

When you define a struct and declare its properties, Swift automatically generates a memberwise initializer for you. This initializer takes parameters with labels that match the names of the struct's properties.

For example, if you have a struct called Person with properties name and age, Swift generates a memberwise initializer like this:

struct Person {
    var name: String
    var age: Int
}

// Swift generates a memberwise initializer like this:
Person(name: String, age: Int)

Memberwise initializers are not automatically provided for classes; you need to write custom initializers for classes if needed.

Q3. How can you customize the behavior of memberwise initializers for a struct?

You can customize the behavior of memberwise initializers for a struct by providing your own custom initializer(s). When you define a custom initializer in your struct, it replaces the default memberwise initializer.

Within the custom initializer, you can perform any custom logic needed to initialize the properties. For example:

struct Temperature {
    var celsius: Double

    init(fahrenheit: Double) {
        self.celsius = (fahrenheit - 32.0) * 5.0 / 9.0
    }
}

If you still want to retain the default memberwise initializer along with your custom one, you can call it explicitly from within your custom initializer using self.init(). For example:

struct Point {
    var x: Int
    var y: Int

    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }

    init() {
        self.init(x: 0, y: 0)
    }
}

Q4. Why Swift does not provide memberwise initializer for classes?

Swift does not provide memberwise initializers for classes primarily due to the fundamental differences in the way classes and structs work.

Inheritance and Superclass Initialization

Classes can be part of class hierarchies where inheritance is common. Superclasses may have their own custom initializers that need to be called properly during subclass initialization.

Memberwise initializers may not handle this inheritance chain and superclasses' initializers correctly, leading to ambiguity and potential issues.

Complex Initialization Logic

Classes can have more complex initialization logic compared to structs. They may need to acquire and release resources, perform setup, and ensure proper state before and after initialization.

Memberwise initializers might not be sufficient to encapsulate all the necessary logic.

Design Choices

Memberwise initializers, while convenient for simple cases, might encourage less thoughtful initialization of class instances, potentially leading to unexpected behavior.

Classes often require more customization and control during initialization. Swift encourages developers to define their own initializers to ensure that the initialization process aligns with the class's requirements.

Q5. What are the Designated Initializers?

  • Designated initializers are the primary initializers for a class or struct. They are responsible for initializing all properties directly declared in that class or struct.
  • Every class or struct should have at least one designated initializer.
  • When you create a subclass, it's customary to call a designated initializer of the superclass before performing any additional setup in the subclass's designated initializer.
class Person {
    var firstName: String
    var lastName: String

    // Designated initializer
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

let john = Person(firstName: "John", lastName: "Murphy")

In this example, init(firstName:lastName:) is the designated initializer for the Person class. It initializes both the firstName and lastName properties directly.

Q6. Can a class or struct have multiple designated initializers?

A class or struct can have multiple designated initializers, each with a different set of parameters. However, it's essential that they initialize all properties declared in the class or struct. Here's an example:

class Rectangle {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    init(squareSide: Double) {
        self.width = squareSide
        self.height = squareSide
    }
}

In this case, Rectangle has two designated initializers, one for rectangles and another for squares.

Q7. What are the Convenience Initializers?

  • Convenience initializers are secondary initializers. They provide an additional way to create instances, often with a subset of properties or with different parameter sets.
  • Convenience initializers must call a designated initializer either directly or indirectly before they complete. This ensures that all properties are properly initialized.
class Person {
    
    var firstName: String
    var lastName: String

    // Designated initializer
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }

    // Convenience initializer
    convenience init(fullName: String) {
        let components = fullName.split(separator: " ")
        
        // Calling the designated initializer
        self.init(firstName: String(components.first ?? ""), lastName: String(components.last ?? ""))
    }
}

let johnMurphy = Person(fullName: "John Murphy")
print(johnMurphy.firstName, johnMurphy.lastName) // Prints: John Murphy

In this example, init(fullName:) is a convenience initializer for the Person class. It splits the full name into first and last names and then calls the designated initializer to set the firstName and lastName properties.

Q8. What is a failable initializer and when should you use a failable initializer?

A failable initializer is an initializer that can return an instance of the class, struct, or enum, or it can return nil if initialization fails. It is declared with the init? syntax, indicating its potential for failure.

Failable initializers are useful when you need to create an instance conditionally and cannot guarantee that initialization will always succeed. Common use cases include parsing data from external sources (e.g., JSON) where the data may not be well-formed or when specific requirements must be met for an instance to be created.

The return type of a failable initializer is an optional. It can either return an instance of the type (if initialization succeeds) or nil (if initialization fails).

Q9. How we can use failable initializer for a custom type?

To define a failable initializer, you declare it with init?, and within the initializer, you perform validation and checks. If the initialization conditions are not met, you return nil. Here's an example:

struct User {
    var name: String
    var age: Int

    init?(name: String, age: Int) {
        guard age >= 0 else {
            return nil // Age cannot be negative
        }
        self.name = name
        self.age = age
    }
}

let alex = User(name: "Alex", age: -5)
print(alex) // Output: nil

Q10. What is a required initializer? Explain with an example.

A "required initializer" is a special type of designated initializer in Swift. It's used in classes and indicates that all subclasses must implement this initializer. Subclasses are required to provide their own implementation of the required initializer.

You would use a required initializer in a class when you want to ensure that all subclasses provide a specific initialization behavior. It enforces a contract that guarantees certain properties or setup must be performed during initialization.

Let's say, you're working on a weather app, and you have a base class called WeatherData that represents weather data. You want to enforce that every subclass of WeatherData provides a required initializer for initializing common properties like temperature and condition.

class WeatherData {
    var temperature: Double
    var condition: String

    // A required initializer for common weather data
    required init(temperature: Double, condition: String) {
        self.temperature = temperature
        self.condition = condition
    }
}

class DailyWeatherData: WeatherData {
    var date: Date

    required init(temperature: Double, condition: String) {
        self.date = Date()
        super.init(temperature: temperature, condition: condition)
    }
    
    init(date: Date, temperature: Double, condition: String) {
        self.date = date
        super.init(temperature: temperature, condition: condition)
    }
}

class HourlyWeatherData: WeatherData {
    
    var time: String

    required init(temperature: Double, condition: String) {
        self.time = "Now"
        super.init(temperature: temperature, condition: condition)
    }
    
    init(time: String, temperature: Double, condition: String) {
        self.time = time
        super.init(temperature: temperature, condition: condition)
    }
}

WeatherData has a required initializer init(temperature:condition:) that ensures any subclass must provide temperature and condition data during initialization.

By using a required initializer in this scenario, you ensure that all subclasses of WeatherData adhere to the contract of providing temperature and condition data during initialization, which is essential for maintaining data integrity in your weather app.

We hope that these interview questions will help you in your iOS interview preparation and also strengthen your basics on Initializers in Swift. We have launched our new e-book "Cracking the iOS Interview" with Top 100 iOS Interview Questions & Answers. Our book has helped more than 372 iOS developers in successfully cracking their iOS Interviews.

Grab your copy now and rock your next iOS Interview!