Since Swift 4, ImplicitlyUnwrappedOptional
or !
as we knew it, became Optional
.
Check:
let a: ImplicitlyUnwrappedOptional<Int> = 1
will spit out the error:
'ImplicitlyUnwrappedOptional' has been renamed to 'Optional'
So instead if we do:
let a: Int! = 1
print(type(of: a)) //will print "Optional<Int>"
It's still Optional<Int>
but indicates to the compiler that it can be implicitly unwrapped.
Implicit Unwrapping is Part of a Declaration.
...
consider !
to be a synonym for ?
with the addition that it adds a flag on the declaration letting the compiler know that the declared value can be implicitly unwrapped.
Ref: Reimplementation of Implicitly Unwrapped Optionals
Now getting to the main question:
If you do:
let a: Int! = 1
let b: Any = a
print(type(of: b)) //prints "Optional<Int>"
It will give the following warning:
Expression implicitly coerced from 'Int?' to 'Any'
or as per Xcode 11
Coercion of implicitly unwrappable value of type 'Int?' to 'Any' does not unwrap optional
Note here that we tried to get a non-optional Any
out of an Int?
which means we were basically expecting an Int
but just by specifying Any
it won't also unwrap the Optional
.
It will remain an Optional
, and this is the meaning behind that warning.
Solutions:
To handle this warning gracefully, we can do any of the following:
let a: Int! = 1
let b: Any? = a
type(of: b) //Optional<Any>.Type
let c: Any! = a
type(of: c) //Optional<Any>.Type
let d: Any = a!
type(of: d) //Int.Type
EDIT: (based on comment)
!
instead of ?
have any practical difference for the programmer?
!
tells the compiler that it can be implicitly unwrapped so it can help ease in the need for optional chaining.
Example:
With ?
class A {
var n: Int? = 1
}
class B {
var a: A? = A()
}
let b: B? = B()
print(b?.a?.n)
/*
but the following won't compile as compiler
will not implicitly unwrap optionals
print(b.a.n)
*/
With !
class A {
var n: Int! = 1
}
class B {
var a: A! = A()
}
let b: B! = B()
print(b.a.n) //compiler will implicitly unwrap `!` similar to print(b!.a!.n)
//also... you can still safely unwrap if you want
print(b?.a?.n)
b.a.n
and b?.a?.n
will both give an Optional<Int>
at the end
- Ofcourse if
b
or a
is nil
then b.a.n
will crash because it's implicitly unwrapping b
and a
to get to n
which is Optional<Int>
- To get
Int
instead of Optional<Int>
, you would do b.a.n!
and so in your case you would do: print(residenceId!)
to get Int
I hope I made sense