Implicitly unwrapped optional is nil but does not cause runtime exception - swift

I was under the impression that implicitly unwrapped optional will cause a runtime exception when used and it is nil. But the following code works without runtime exception, why?
var str:String?
println(str!) // Crashes as expected
var str:String! // Implicitly unwrapped
println(str) // Does not crash, not what I expect - it prints nil

It prints the variable as enum (i.e. optional), because internally an optional is enum Optional<T>.
More precisely, I presume it uses the debugDescription property, in fact this is what happens:
var str:String?
println(str) // Prints "nil"
str.debugDescription // Prints "nil"

An implicitly-unwrapped optional is only forcibly unwrapped in a situation which expects a non-optional. println() accepts all types, including optionals, and so there is no need to forcibly unwrap it before passing to println(). Since it is not unwrapped, it does not crash.

Related

Why does a `nil` implicitly unwrapped optional print `nil` and not crash? [duplicate]

This question already has answers here:
Explicitly unwrapping optional nil does not cause crash
(2 answers)
Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
(1 answer)
Closed 3 years ago.
I have an implicitly unwrapped optional with value nil.
Why does it print nil and not crash?
var x : Int!
print(x) // nil
That does not crash because print accepts Any as the first parameter. Are implicitly unwrapped optionals a kind of Any? Yes they are! Anything is Any. There is no need to unwrap the optional. An implicitly unwrapped optional can be used in a place where Any is expected without unwrapping the optional.
That could potentially be confusing because now you have something with type Any, which doesn't look like it's optional, but it is an optional under the hood. To avoid this, Swift will output a warning telling you that you are implicitly coercing whatever optional type to Any.
You need to use ! to force unwrap it here:
print(x!)
The reason why it's not crashing is because you are not force-unwrapping it in print(x). It will only crash one you try to force-unwrap it like print(x!)
IUO(Implicitly Unwrapped Optionals) are just special type of Optionals which will be automatically unwrapped one you use it inside chaining (say optional chaining), otherwise they remain Optionals.
Consider an example:
var implicitlyUO: Int!
implictlyUO = 4
print(implicitlyUO) // prints Optional(4)
print(implicitlyUO.advanced(by: 3)) // prints 7
implicitlyUO = nil
print(implicitlyUO) // prints nil
print(implicitlyUO.advanced(by: 3)) // Here it will crash as now it will be unwrapped and found it nil
var someNilValue:Int?
someNilValue = 4
print(someNilValue) // prints Optional(4)
print(someNilValue?.advanced(by: 3)) // prints Optional(7)
someNilValue = nil
print(someNilValue) // prints nil
print(someNilValue?.advanced(by: 3)) // prints nil
print(someNilValue!.advanced(by: 3)) /* Will crash here as we are force unwrapping nil which is the same case as implicitlyUO */
The only advantage you get with IUO is that you don't need ! (or explicitly unwrapping) in your code unnecessarily but you need to make sure that it is not nil.

Implicit Unwrapped Optional

I am using playground to run the below code
var a : Int!
a = nil
print(a) o/p - none
print(a!) o/p - crash
a = 5
print(a) o/p - some(5)
print(a!) o/p - 5
I know optionals is enum and it has two type none or some.
But as I am declaring a as implicitly unwrapped I think I don't have to unwrap it to get the actual data.
Whether I have understood optionals wrong ?
As others have said, IUOs (implicitly unwrapped optionals) are now regular optionals with some hints to the compiler that gives it permission to unwrap them.
That being said, print is handled differently. Try using an assignment to a non-optional variable instead. That's a better test, e.g:
var a : Int! = nil
let b: Int = a
Here’s a use case for implicitly unwrapped optionals. In any class, all properties have to be initialised upon initialisation of the class instance. You can either assign the properties a default value or use the init function for property initialisation.
In a view controller, however, you don’t want to use an init function. Some properties might not have default values but will rather be initialised during viewDidLoad. In this case you could declare the property as implicitly unwrapped because it won’t be accessed before view controller loading—and after that you can make sure in viewDidLoad (or in the calling view controller’s prepareForSegue method, for example) that it is not nil, hence safe to be accessed from now on.
Just my two cents to add to your understanding of IUOs.

The difference between Swift Optional Property Declarations [duplicate]

This question already has answers here:
Swift variable decorations with "?" (question mark) and "!" (exclamation mark)
(1 answer)
What is the difference between String? and String! (two ways of creating an optional variable)?
(7 answers)
Closed 4 years ago.
I noticed that some coding examples for Swift declare optional properties in different ways. However, I seem to have trouble trying to tell them apart (or, rather, when to use each.)
class MyClass {
// I believe this can start as nil but should always be set
// once it is.
var optionalProperty1: Type!
// I believe this can be set or nil anytime.
var optionalProperty2: Type?
// I think this is the same as
// var optionalProperty3: Type!
lazy var optionalProperty3: Type
}
How does each one differ from the others and when should each one be used?
var optionalProperty1: Type!
When you're sure you will have value for this property such as timestamp it will be something for sure. And Yes it can be nil too.
var optionalProperty2: Type?
When you're not sure about the value (Or this field is not mandatory) take it as optional for example:- If I make a Person class address can be optional and name will not.
lazy var optionalProperty3: Type
This syntax is wrong you can not declare lazy property in this way. You must assign something to it initially. See below example:
/// First way
lazy var optionalProperty3: String = {
return "Hello"
}()
/// Second way
lazy var optionalProperty4 = "Hello"
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration. lazy variables are great for things that need to be setup once, then never re-set.
One more thing you really don't need to specify type in modern Swift. Means if you will assign 0 it will be an integer itself, if you will assign 0.0 it will take it as double and same for String, Array etc.
The third declaration is not an optional.
The third one declares a lazy property. Lazy properties will only be initialised when they are first used. Example:
class A {
lazy var a: Int = {
print("hello")
return 1 + 1
}()
}
let a = A()
print(a.a)
If you remove the last line, hello will not be printed.
The first declaration is a implicitly unwrapped optional while the second declaration is a normal optional.
When you access members of a normal optional, you need to unwrap it with ? or !:
var myInt: Int? = ...
print(myInt.description) // doesn't compile, must unwrap
print(myInt!.description) // will crash if myInt is nil
print(myInt?.description) // will print "nil" if myInt is nil
On the other hand, implicitly unwrapped optionals do this implicitly - whenever you try to access a member, it will implicitly unwrap it with ! for you:
var myInt: Int! = ...
print(myInt.description) // equivalent to "myInt!.description"
From Apple's Swift documentation:
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."
Implicitly Unwrapped Optionals (!): "As described above, optionals indicate that a constant or variable is allowed to have “no value”. Optionals can be checked with an if statement to see if a value exists, and can be conditionally unwrapped with optional binding to access the optional’s value if it does exist.
Sometimes it’s clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it’s useful to remove the need to check and unwrap the optional’s value every time it’s accessed, because it can be safely assumed to have a value all of the time.
These kinds of optionals are defined as implicitly unwrapped optionals. You write an implicitly unwrapped optional by placing an exclamation mark (String!) rather than a question mark (String?) after the type that you want to make optional.
Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties."
Read more at https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
Explicitly Unwrapped Variable
var optionalProperty1: Type!
This means that the value should never be nil. It will always be initialized but it is better to use var optionalProperty1: Type
Optional
var optionalProperty2: Type?
This is an optional value, meaning that it can either have a value or be nil. normally to use the value you would need to unwrap it. using either conditional unwrapping or a guard statement...
if let value = optionalProperty2 {
print("optionalProperty2 had a value, value is set")
}
guard let value = optionalProperty2 else {
print("optionalProperty2 was nil value is nil")
}
or you can just check if it has a value and explicitly unwrap it (which is not considered best practice)
if optionalProperty2 != nil {
print("optionalProperty2 is set to \(optionalProperty2!)")
}
Lazy Variable
lazy var optionalProperty3: Type a lazy variable is different, it is not an optional unless you define it to be optional. Lazy variables do not initialise to a value until the value is first used. So if you do not call/use the variable it will never be set.

Why is the ! in Swift called an 'implicitly' rather than 'explicitly' unwrapped optional?

The name of the ! always confuses me: it's called an 'implicitly unwrapped optional'. However, what is implicit about it? Implicit means "implied though not plainly expressed." However, does not adding a ! plainly express its purpose? Does not adding a ! make it explicit what we are trying to accomplish?
In Swift, trailing exclamation marks (!) are used in two different ways. One is called Forced Unwrapping. This is when you have a variable defined as an Optional and you want to basically assert that the value is not nil so that you can use it as if it were not an optional:
var optionalName: String? = "World"
if optionalName != nil {
sayHelloTo(optionalString!)
}
An alternate way you could describe "Forced Unwrapping" is "Explicit Unwrapping", but forced adds the extra hint that the whole program will crash if you try to "Force Unwrap" an optional that is nil.
The second is when you are actually declaring the type of a variable and it is called an Implicitly Unwrapped Optional. This is for when you want to declare a variable that is technically optional, but that you will treat as if it is not optional. Every time you use this Implicitly Unwrapped Optional, it is in reality, doing the "Force Unwrapping" I described above:
var name: String! = "World"
if name != nil {
sayHelloTo(name)
}
You can still test an Implicitly Unwrapped Optional for nil, but you can also use it directly as if it were not optional. That is why it is considered implicit. Every time you use it, it is automatically, implicitly unwrapped for you.
Like "Forced Unwrapping" an "Implicitly Unwrapped Optional" will still crash the entire program if you try to use it when it is nil
Normal Optional
var foo : Foo? = Foo()
foo!.doSomething() // explicitly unwrap it and call the method
Implicitly Unwrapped Optional
var foo : Foo! = Foo()
foo.doSomething() // implicitly unwrap it and call the method just like it is not optional
In both case, you need something to declare an optional (? or !). Implicitly Unwrapped Optional does not add more. But you can omit unwrap operator when use it.

Optional Binding on Implicitly Unwrapped Optional

Swift Programming Guide says "You can also use an implicitly unwrapped optional with optional binding, to check and unwrap its value in a single statement". Why do you need to use optional binding when the value is already unwrapped? Does option binding unwrap it again?
Calling an implicitly unwrapped is the same as calling a regular optional with ! after it. It can still hold a nil value and calling it when it's nil will result in a runtime error, so you use the if let optional binding if you aren't sure if it is nil or not.
var myOptional: Int! = nil
10 + myOptional //runtime error
if let myUnwrapped = myOptional{
10 + myOptional //safe
}
Why do you need to use optional a binding when the value is already
unwrapped
It is not already unwrapped. An implicitly unwrapped optional is just an optional. It implicitly unwraps when used in certain expressions (postfix expressions, the same expressions where optional binding has an effect). But otherwise, it's just an optional, not unwrapped. You can use optional binding with it like with other optionals.