Logan
Logan

Reputation: 53112

Why do I need to declare an optional value as nil explicitly in Struct - Swift

Here's a quote from the docs:

If your custom type has a stored property that is logically allowed to have “no value”—perhaps because its value cannot be set during initialization, or because it is allowed to have “no value” at some later point—declare the property with an optional type. Properties of optional type are automatically initialized with a value of nil, indicating that the property is deliberately intended to have “no value yet” during initialization.

If I do this with a class it works fine:

class MyClass {
    var someProperty: String?
}

var myClass = MyClass()
myClass.someProperty // Shows nil

However, if I do this with a struct type, I get an error on initialization:

struct MyStruct {
    var someProperty: String?
}

// ERROR
var myStruct = MyStruct()

Error:

Missing argument for parameter 'someProperty'

I can remedy this by declaring it nil explicitly like so:

struct MyStruct {
    var someProperty: String? = nil
}

// Valid
var myStruct = MyStruct()

Question

Given the documentation, I would expect properties on any type that are set as optionals to be defaulted to nil. Is there a reason I have to declare it explicitly on a struct?

Why?

No good reason, like many of you, I'm just experimenting.

Upvotes: 10

Views: 14750

Answers (3)

Cezar
Cezar

Reputation: 56332

Both Classes and Structs need to have all property values set when they are initialized. This can be done either through explicit default values or by setting a value in the designated initializer.

However, Structs differ in the fact that they have an automatically generated memberwise initializer.

When you don't define a value for someProperty explicitly, your struct has one initializer only: the automatically generated memberwise one.

If you do provide a default value, you get two: one that takes no arguments, and one that takes a value for someProperty as an argument

From the docs:

All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:

let vga = Resolution(width: 640, height: 480)

Unlike structures, class instances do not receive a default memberwise initializer. Initializers are described in more detail in Initialization.

Upvotes: 13

user3675131
user3675131

Reputation: 3245

I agree this is rather quirky (unless I'm also missing something). For structures with only optionals, it might be worth suggesting (via Apple bugreport) that in such cases, a default parameterless initialiser is also added by default?

Another remedy is

var myStruct = MyStruct(someProperty:nil)

However, if you had a lot of optional members, this becomes clumbsy.

Upvotes: 1

67cherries
67cherries

Reputation: 6951

I think this is an deliberate difference between structs and classes, which makes a bit of sense. For example when you have a struct, say a 3d point with three floats for XYZ. It doesn't make much sense to have a nil value for x or y or z. With a class on the other hand this is a very important feature. If you think about a downloader class, for example, that goes and downloads a text file and stores it in a property. It makes more sense for that property to be nil when the class is first initialized. Since apple has changed structs to be much more closely related to classes I think this is an important distinction. It's my opinion that setting the optional explicitly to nil is a bug.


My reasoning for this:

In the optional documentation all of the example are on classes.

Upvotes: 0

Related Questions