I'm starting to get my head around optionals and forced unwrapping, except for in one particular context: when it is a return type to a function.
What is the difference between:
func myFunction() -> NSData { ... }
func myFunction() -> NSData! { ... }
func myFunction() -> NSData? { ... }
Furthermore, when I use a return value of NSData!
, I am forced to use ?
which seems odd.
func myFunction() -> NSData! { ... }
let data = myFunction()
data?.write()
Why do I need the ?
if I force unwrapped the return?
func myFunction() -> NSData { ... }
The above means that myFunction
returns an instance of NSData
.
func myFunction() -> NSData? { ... }
The above means that myFunction
returns a value of type Optional<NSData>
(also called NSData?
). Optional
is an enum
with two cases: .some(value)
and .none
(also called nil
). So the function returns either an NSData
(wrapped in the .some
case), or nil
.
func myFunction() -> NSData! { ... }
The above means that myFunction
returns a value of type Optional<NSData>
, just like the NSData?
return type in the previous example.
However, the use of !
means that, if you use the value of myFunction()
in a way that doesn't type-check, the compiler will try unwrapping the returned value for you. So if you say this:
let maybeLength = myFunction()?.length
then the compiler will see that you are treating the return value of myFunction
as an Optional<NSData>
. But if you say this:
let dataLength = myFunction().length
then the compiler will see that Optional<NSData>
doesn't have a length
member, so it will pretend you wrote this:
let dataLength = myFunction()!.length
and if that compiles, it will carry on.
This behavior was defined in Swift Evolution proposal SE-0054, Abolish ImplicitlyUnwrappedOptional
type.
Now let's finally consider this:
func myFunction() -> NSData! { ... } let data = myFunction() data?.write()
What is the type of data
? The compiler has to infer the type of data
based on the expression on the right side of the =
. As I explained in the example above, the type of myFunction()
is Optional<NSData>
. So the type of data
is Optional<NSData>
, also called NSData?
.
The compiler doesn't run into any trouble making data
's type NSData?
, so it has no reason to implicitly unwrap the return value of myFunction
.