Constant Unassigned Optional Will Not Be Nil by Default

Constant unassigned optional will not be nil by default

Yes it's correct

An optional variable doesn't need to be manually initialized. If you read it before having populated it does contain nil.

From Apple docs

If you define an optional variable without providing a default value, the variable is automatically set to nil for you [...]

On the other hand the compiler does force you to manually initialize an Optional constant (let) before you can read it.

Unlike a variable, the value of a constant cannot be changed once it is set. Attempting to do so is reported as an error when your code is compiled [...]

Why?

A constant can be written only once. It doesn't need to happened on the same line it is initialized but it must happened before your read it.

E.g. this code works fine

let num: Int?
num = 1
print(num)

However if the compiler had put a temporary nil value inside num then the constant would have been wrote twice. Which is against the concept of constant.

let num: Int?
print(num) // nil ??? <- this can't work!
num = 1
print(num) // 1

Another example

This code snippet works fine

func printArea(width: Int?, height:Int?) {
let area: Int?
if let width = width, height = height {
area = width * height
} else {
area = nil
}
print(area)
}

Again, if the compiler had put a temporary nil value inside area then...

func printArea(width: Int?, height:Int?) {
let area: Int?
print(area) // not possible! area is going to change in a moment
if let width = width, height = height {
area = width * height
} else {
area = nil
}
print(area)
}

Why optional constant does not automatically have a default value of nil

Not setting a read-only (constant) field with either an:

  • initialization expression
  • initializer

is almost certainly an indication of an error in your program.

Since you have no other opportunity to set the value of your let field, the value of the field is going to remain nil (or some other default). It is rather unlikely that a programmer would find such behavior desirable, and request it on purpose.

That is why Swift marks this situation as an error. On the other hand, if you actually wanted your String constant to remain nil, you could add an expression to set it to nil, and silence the error:

let owner: String? = nil // Pretty useless, but allowed

Swift - use of optional with let

A constant that's an optional needs to be assigned a value during the init process. That value can be nil, or some other value. Once assigned it is stuck in that value. A nil is like a "this property intentionally left blank" indicator, written in permanent ink.

Say you have a class that gets filled with response data from a network request. Some of the fields you get back may be nil, or they may contain data.

You write code that parses the response from the server and builds a response object. Each property of the response object is fixed. It either contains data if you got information for that property, or nil.

In that case it makes perfect sense to use an optional constant.

You'd write an init method for your response object that would take the network reply (In JSON, for example) and fill out the properties of the response object. If a given tag in the JSON data is missing, you'd set that property to nil. You use a constant because the value is fixed once the response object is initialized. If it's nil, it will be nil forever. If it contains a value, it will always contain that value and it can't be changed.

Will optional values be de-initialized automatically?

Is it required to explicitly set optional values to nil

No, Automatic Reference Counting frees the memory automatically. Unless there is a circular reference, e.g., there is a strong reference to ClassA in ClassB and vice-versa. Also, Automatic Reference Counting only applies to instances of classes and not value types (String, Int, Enum, etc). The memory of these value types are freed when their parent instances are deinitialized.

Is that only the difference?

var someVar:String! creates an Implicitly Unwrapped Optional, which is basically an optional that is automatically unwrapped when accessed. Accessing an Implicitly Unwrapped Optional when it's nil causes a runtime error.

Providing a default value for an Optional in Swift?

Update

Apple has now added a coalescing operator:

var unwrappedValue = optionalValue ?? defaultValue

The ternary operator is your friend in this case

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

You could also provide your own extension for the Optional enum:

extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}

Then you can just do:

optionalValue.or(defaultValue)

However, I recommend sticking to the ternary operator as other developers will understand that much more quickly without having to investigate the or method

Note: I started a module to add common helpers like this or on Optional to swift.

initialize a struct without the optionals properties

you can use default value for the properties.

init(presentValue: Double, rate: Double, time: Double, frequency: Double = 0.0) {
...
}

When an instance of a class is initialized, what is the sequence?

You cannot assign a let variable more than once - however, you can define it and leave it uninitialized. Then in your init method, you can have "nobody" as the default value for the agent argument.

class Actor {
let agent: String

init(agent: String = "nobody"){
self.agent = agent
}
}

print(Actor().agent) // "nobody"
print(Actor(agent: "xyz").agent) // "xyz"

As Alexander suggested in the comments below, if you have too many arguments in your init method, default values can get a little messy. Consider creating a separate init method that sets the default values.

class Actor {
let agent: String
...

init() {
self.agent = "nobody"
...
}

init(agent: String, ...){
self.agent = agent
...
}
}


Related Topics



Leave a reply



Submit