Sam Fischer
Sam Fischer

Reputation: 1472

Is using nested initializers in Swift bad practice?

Say I have a Swift struct setup like this :

struct User {
    // Properties
    var name: String?
    var username: String!
    var email: String?
}

Now, the way I look at it, there are 2 ways of designing the initializer.

Here's the first:

init(username: String) {
    self.username = username
}

init(username: String, name: String) {
    self.username = username
    self.name = name
}

init(username: String, name: String, email: String) {
    self.username = username
    self.name = name
    self.email = email
}

Here's the second :

init(username: String) {
    self.username = username
}

init(username: String, name: String) {
    self.init(username: username)
    self.name = name
}

init(username: String, name: String, email: String) {
    self.init(username: username, name: name)
    self.email = email
}

Which is the better practice and does it even make a difference ?

Upvotes: 2

Views: 786

Answers (2)

vadian
vadian

Reputation: 285290

Actually you need only one initializer at all.

username seems to be required, so declare it as non-optional.

If you provide a default value for the other parameters they could be omitted.

struct User {
  // Properties
  var name: String?
  var username : String
  var email: String?

  init(username: String, name: String? = nil, email: String? = nil) {
    self.username = username
    self.name = name
    self.email = email
  }
}

Now you can use these three forms with one initializer

User(username: "Foo")
User(username: "Foo", name: "Bar")
User(username: "Foo", name: "Bar", email:"john@doe.com")

In this case I'd recommend to declare all properties as non-optionals. The absence of a value can be represented with an empty string and you have never to deal with optional bindings or forced unwrapping.

struct User {
  // Properties
  var name, username, email : String

  init(username: String, name: String = "", email: String = "") {
  ...

The behavior of the initializer is exactly the same

Upvotes: 11

Edward Anthony
Edward Anthony

Reputation: 3464

This is not correct. Based on Apple Documentation, if you want to make multiple initializer that does the same thing you could use convenience initializer like this. Convenience initializer will finally call the designated initializer.

convenience init(username: String?) {
    self.init(username: username, name: nil)
}

convenience init(username: String?, name: String?) {
    self.init(username: username, name: name, email: nil)
}

// designated initializer
init(username: String?, name: String?, email: String?) {
    self.init(username: username, name: name)
    self.email = email
}

Now you can call it like this

let user = User(username: "john")

or

let user = User(username: "john", name: "John Doe")

or

let user = User(username: "john", name: "John Doe", email: "johndoe@domain.com")

Upvotes: 1

Related Questions