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
Uialertcontroller - Add Custom Views to Actionsheet
Whither Dispatch_Once in Swift 3
Getting the Decimal Part of a Double in Swift
How to Remove Diacritics from a String in Swift
Transparent Background For Modally Presented Viewcontroller
How Change Background Color If Using Navigationview in Swiftui
Xcode Swift Am/Pm Time to 24 Hour Format
How to Make a Random Color With Swift
When Should I Access Properties With Self in Swift
Failing Cast in Swift from Any? to Protocol
Why My Return Is Nil But If I Press the Url in Chrome/Safari, I Can Get Data
Printing a Variable Memory Address in Swift