Isuru
Isuru

Reputation: 31323

Return from initializer without initializing all stored properties

I have a simple class like this.

public class User {
    let id: Int
    let firstName: String
    let lastName: String
    let email: String?

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }
}

This compiled just fine in previous Swift version. In Swift 1.2, I get the following compilation error.

Return from initializer without initializing all stored properties

Why is that and how can I resolve it?

Upvotes: 63

Views: 95524

Answers (5)

Dániel Nagy
Dániel Nagy

Reputation: 12015

If a property is constant, so created with let, you have to initialize it in place or in the init method, even if it is an Optional. If you want to be able to set email optionally, you should change let to var. In other words, if you are not initializing a variable in either the init method or class body, then the variable must be both a var and an Optional.

Related statements in the docs:

You can assign a value to a constant property at any point during initialization, as long as it is set to a definite value by the time initialization finishes. Once a constant property is assigned a value, it can’t be further modified.

For class instances, a constant property can only be modified during initialization by the class that introduces it. It cannot be modified by a subclass.

Upvotes: 92

Tiago Almeida
Tiago Almeida

Reputation: 14237

The rule of thumb is:

  • If you have let, you need to initialize it (even if it is optional). Eg : let email: String
  • If you have a non optional var you need to initialize. Eg var email: String
  • If you have an optional var you don't need to initialize it. Eg var email: String?

Upvotes: 40

Chamath Jeevan
Chamath Jeevan

Reputation: 5172

Change the email from "let" to "var" as below.

public class User {
    let id: Int
    let firstName: String
    let lastName: String
    var email: String?

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName

    }
}

Upvotes: 16

Onato
Onato

Reputation: 10221

You need to explicitly set a value for email since it is a constant.

public class User {
    let id: Int
    let firstName: String
    let lastName: String
    let email: String?

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
        self.email = nil // <--------------
    }
}

Or as the others mentioned you can change email to a variable.

Upvotes: 24

Saad
Saad

Reputation: 8947

First of all make it clear that every let variable must be assigned value at declaration time. So your statements will be

let id: Int  = 0
let firstName: String = "test"
let lastName: String = "Test"
let email: String? = "Test"

Secondly in classes, you must have to initialize variables or define them as optional types by either putting '?' or '!' with every variable. Like

let id: Int!
let firstName: String!
let lastName: String!
let email: String?

or

let id: Int?
let firstName: String?
let lastName: String?
let email: String?

But want to say you here that these variables will not be able to change as they are constants. so you must use var with these if you'r not passing value at time of declaration. Your final code in this case will be some kind of this

var id: Int
var firstName: String
var lastName: String
var email: String?

Upvotes: 7

Related Questions