1

I have the following struct:

struct Person {
   let name: String
   let age: Int
   let assets: Double
}

To initialize a person, I would like to pass it a dictionary that contains the name and age, as well as info to calculate the assets:

public init(info: [String : AnyObject]) {
        if let name = info["name"] as? String {
            self.name = name
        }

        if let age = info["age"] as? Int {
            self.age = age
        }

        if let assets = info["assets"] as? [String : AnyObject] {
            calculateAssets(assets: assets)
        }
    }

    mutating func calculateAssets(assets: [String : AnyObject]) {
        self.assets = 1+2+3.4  // really do this with info from the dictionary
    }

With this setup, I get two compiler errors:

  1. 'self' used before all stored properties are initialized
  2. Return from initializer without initializing all stored properties

Following the compiler suggestions, I added a default value for each property, and changed them to be a var:

struct Person {
    var name: String = ""
    var age: Int = 0
    var assets: Double = 0.0

// init ...
}

And indeed, the compiler errors are gone.

But am I on the right track by making these corrections?

2 Answers 2

1

The problem is that in your init function you might initialize the variables but you can't be sure, since the conditions of the if statements can be false. This is why the compiler is giving you the errors (also because you are trying to call self.assets in another function when the variable might still not be initialized - so you at least need to change this one to a var).

If you can't be sure that the values in the info dictionary are valid you should change your variables to var.

Now you have two choices:

  • Give your variables a default value (like you did in your example)
  • Declare your variables as Optionals (like suggested by @Özgür).

Your choice depends on what makes more sense. If your default values make sense for your situation and you can work with the variables having those values then I'd go with that.

Otherwise, you should go with the Optionals. Optionals obviously have the plus that you don't need to initialize them but then the con is that you'll need to implicitly or explicitly unwrap them later when you want to use them (using ? or !).

If - for whatever reason - you can be sure that the values in the info dict are valid - you could also leave your name and age as constants (let) and just explicitly unwrap the dictionary values when you assign them:

self.name = info["name"] as! String

self.age = info["age"] as! Int

But as I said this would only work if info["name"] and info["age"] contain valid values, otherwise you will get a runtime exception. So the "default value" or "Optional" choices are your safe and clean options, whereas this is the quick and dirty way.

Sign up to request clarification or add additional context in comments.

4 Comments

Got it. And even if the values are ok, I could get a runtime error if I make a typo: info["naem"]. So I will just go with the default values or the optionals, I need to think about that.
And calling a function from init is ok to calculate a value?
Yes, as long as the variable you're setting is declared as a var with either a default value or as an Optional.
whenever info["name"] as! String unwrap fails your app will crash so i dont advice that method.
1

You got compiler error because your variables are not inited when you set them.(you define them as inited). That's why for second case when you init them to nil values, error is gone. For this conditions, Swift has optionals.Can be nil and a value at the same time. Check here. You can add ? and that makes the variable optional.

struct Person {
    var name: String?
    var age: Int?
    var assets: Double?

// init ...
}

2 Comments

However, the name is required (a person must have a name), so can it still be an optional ?
it is not about that @Koen, you should check optionals for sure

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.