Understanding Optionals

I'm learning Swift and trying to understand Optionals.


Given this code:


var str1:String?
var str2:String!
println("str1: \(str1)")
println("str2: \(str2)")

Results:

str1: nil

str2: nil


So if a implicitly unwrapped string variable can be nil, why would one ever declare an Optional string or (Optional <any type>)?

Generally, declaring something as a normal optional (with Type?) indicates that an instance or value can be nil under normal circumstances, or might become nil in the future.


When something is declared as an implicitly unwrapped optional (with Type!), it's still an optional, but it usually represents an instance or value that might be nil when first created but should always have a valid value later on, or a return value that is nil under rare circumstances. It doesn't need to be unwrapped each time it is used, but will crash your code at runtime if it is nil, so it's a good idea to test it when first created/returned.

The major reason to use an optional is to make the compiler force the programmer to handle the nil case. Whether you think that is a good idea or not depends largely on if you think static typing is a good idea or not. Optionals fills a hole in the type system, like generics.

>but should always have a valid value later on, or a return value that is nil under rare circumstances


This is subjective, and I think it being subjective will lead to different uses and confusion. I would have rather seen Swift provide a single way to declare that a variable may be nil.


var int1:Int?
var int2:Int!
println("int1: \(int1)")
println("int2: \(int2)")
int1 = 1
int2 = 2
println("int1: \(int1)")
println("int2: \(int2)")
int1 = nil
int2 = nil
println("int1: \(int1)")
println("int2: \(int2)")

Results:

int1: nil

int2: nil

int1: Optional(1)

int2: 2

int1: nil

int2: nil


Thanks for your reply.

In ObjC I think it is pretty nice to be able to send messages to nil at times.

You still can "send messages to nil", sort of, by optional chaining:


let a: SomeClass? = …

a?.someMethod (…)


If there's a return value, say an Int, it's going to produce an optional type:


let b: Int? = a?.someMethod (…)


So you can do all the same things, you just have to deal with optionals properly. Not quite the same thing, but safer.

You can safely call the methods of a nil object in Swift.


ObjC

[obj doSomething];


Swift

obj?.doSomething()

This is how I understand it:


In Objective-C, all class instance variables are what would be called Optional in Swift, because all of them can potentially be nil.


I have found for myself it is better to think of Swift as adding "non-optionalness". Meaning, you can now declare that values will never be nil, and then not have to worry about checking if they are, or code silently failing. Although you can put in checks for this, it is not something that exists at compile time in Objective-C.


The "!" (implicityly unwrapped optional) was there mainly for compatibility with existing Objective-C libraries for convenience. Although many API calls could potentially return nil for some values, in practice the internal implementation prevented this from happening. By importing the call with the "!" modifier, this tells you that the value will not be nil, and also points out that nothing in the complier enforces that, and if it is nil for some reason the application will crash. This made things a lot less painful in the Swift code that uses those libraries.


The implicity unwrapped optional mostly becomes irrelevant as Objective-C APIs are annotated with the new nullability indicators introduced at WWDC, and the libraries can be accessed with simple optional/non-optional typing.

Understanding Optionals
 
 
Q