Hi all, I want to when to use optionals. I fully understand what an optional is and how to unwrap them. What I am not fully confident about is when to use it. Every time I declare an instance I always do it like this var number = Int()
The most general guideline I can think of is: use Optionals when nil
is a meaningful value.
The Swift Programming Language - Basics
Optionals
You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all.
NOTE
The concept of optionals doesn’t exist in C or Objective-C. The nearest thing in Objective-C is the ability to return
nil
from a method that would otherwise return an object, withnil
meaning “the absence of a valid object.” However, this only works for objects—it doesn’t work for structures, basic C types, or enumeration values. For these types, Objective-C methods typically return a special value (such asNSNotFound
) to indicate the absence of a value. This approach assumes that the method’s caller knows there’s a special value to test against and remembers to check for it. Swift’s optionals let you indicate the absence of a value for any type at all, without the need for special constants.Here’s an example of how optionals can be used to cope with the absence of a value. Swift’s
Int
type has an initializer which tries to convert aString
value into anInt
value. However, not every string can be converted into an integer. The string"123"
can be converted into the numeric value123
, but the string"hello, world"
doesn’t have an obvious numeric value to convert to.The example below uses the initializer to try to convert a
String
into anInt
:
- let possibleNumber = "123"
- let convertedNumber = Int(possibleNumber)
- // convertedNumber is inferred to be of type "Int?", or "optional Int"
Because the initializer might fail, it returns an optional
Int
, rather than anInt
. An optionalInt
is written asInt?
, notInt
. The question mark indicates that the value it contains is optional, meaning that it might contain someInt
value, or it might contain no value at all. (It can’t contain anything else, such as aBool
value or aString
value. It’s either anInt
, or it’s nothing at all.)
...
The problem with nil
is that it's an old-timey word that nobody uses, which was chosen for familiarity to Objective-C developers (which I would guess used it because it was a very short word, but Objective-C was known for being verbose so I don't get it). none
is better because it's still used in modern speech; we maybe should deprecate nil
at this point.
I'm not sure that the semantics of none
work, though. Given the question, "How many scoops of ice cream does Jessy like on hot apple pie?", the answer may be 2
or none
or we don't know
. The virtue of nil
is that's not really used for anything in modern speech.
If we want to bring the semantics of "don't know" into Swift, how about replacing nil
with dunno
?? (j/k, of course)
You can certainly write var number = Int()
if you'd like. This will initialize number
to zero. However, when you read the value of that variable later, you may have trouble distinguishing whether any zero is the meaningful result of, say, a very difficult computation or still just the placeholder you assigned initially.
If you're not ready to initialize the value where you declare the binding, you may want to consider just writing var number: Int
(or let number: Int
, as the case may be). You'll note that you can't read the value of a variable that hasn't first been initialized.
What is the role of Optional
in all this? When dealing with real-world data, you'll often find that some values are missing. A user may choose not to fill out part of a form, for example, or you may have a list of measured values from a device where certain measurements might not have been taken.
It can be a major source of errors when you don't take into account how missing data is represented. For example, if I'm calculating the average temperature throughout the day as measured across all of my smart thermostats, I don't want missing data to be represented as 0 or as any other number, because that would skew my average unless I know to take out these fake results. To do so, however, I'd have to know what arbitrary number the smart thermostat decided to use as placeholder meaning that there's no temperature information, and critically I'd have to remember to deal with this scenario.
Internally, once I've ingested the smart thermostats' data, I can avoid having to carry on using an arbitrary number for missing data and instead represent temperatures as a list (array) of optional numbers. That way, nil
can represent missing data, and Swift will remind me when I've forgotten to consider the possibility that data might be missing. For example, when I try to calculate an average, Swift will tell me that I have to unwrap each data point first and choose what to do when a data point is nil
.