Why create Implicitly Unwrapped Optionals , since that implies you know there's a value?
Consider the case of an object that may have nil properties while it's being constructed and configured, but is immutable and non-nil afterwards (NSImage is often treated this way, though in its case it's still useful to mutate sometimes). Implicitly unwrapped optionals would clean up its code a good deal, with relatively low loss of safety (as long as the one guarantee held, it would be safe).
(Edit) To be clear though: regular optionals are nearly always preferable.
swift - Implicit unwrapped optionals
It's all related to the class initialization.
take Outlets for example they're force unwrapped because we know they will hold a value after initialization from the XIB or Storyboard but they will not be set before the class initialization.
A force unwrapped optional exits to tell the compiler I'm taking the responsibility to make sure this variable will be set before calling it.
in your example I don't think it makes sense to write:
let aString: String! = "this is a test string"
It should just be as you wrote:
let aString: String = "this is a test string"
It makes more sense to have:
var aString: String!
meaning you'll take ownership of this variable initialization (i.e making sure it's not nil)
Why does a `nil` implicitly unwrapped optional print `nil` and not crash?
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!)
How to use Implicitly Unwrapped Optionals?
As of Swift 1.0
If your deployment target is 10.10 you can use the convenience method introduced with Yosemite.
let context = NSGraphicsContext.currentContext().CGContext
If you have to support 10.9 you'll have to cast the context manually as per below.
let contextPtr = NSGraphicsContext.currentContext().graphicsPort
let context = unsafeBitCast(contextPtr, CGContext.self)
Difference between Force Unwrapping Optionals and Implicitly Unwrapped Optionals
First of all let's define an Optional
An Optional value is a container of some type (Int
, String
, UIColor
, ...), it could contain the value (1
, "Hello world"
, .greenColor()
, ...) or nil
.
let anOptionalInt: Int? = 1
let anotherOptionalInt: Int? = nil
When in Swift we see an Optional value we think:
Ok this could contain the actual value or
nil
Force unwrapping
It's the action of extracting the value contained inside an Optional
.
This operation is dangerous because you are telling the compiler: I am sure this Optional value does contain a real value, extract it!
let anOptionalInt: Int? = 1
let anInt: Int = anOptionalInt!
Now anInt
contains the value 1.
If we perform a force unwrapping on an Optional value that happens to contain nil
we get a fatalError
, the app does crash and there is no way to recover it.
let anotherOptionalInt: Int? = nil
let anotherInt = anotherOptionalInt!
fatal error: unexpectedly found nil while unwrapping an Optional value
Implicitly unwrapped optionals
When we define an Implicitly unwrapped optional, we define a container that will automatically perform a force unwrap each time we read it.
var text: String! = "Hello"
If now we read text
let name = text
we don't get an Optional String
but a plain String
because text
automatically unwrapped it's content.
However text is still an optional so we can put a nil
value inside it
text = nil
But as soon as we read it (and it contains nil
) we get a fatal error because we are unwrapping an optional containing nil
let anotherName = text
fatal error: unexpectedly found nil while unwrapping an Optional value
Alternative to implicitly unwrapped optional using @propertyWrapper in swift
You can simulate implicitly unwrapped optionals with a property wrapper as follows:
@propertyWrapper
struct MaybeUninitialized<T> {
private var storage: T?
var wrappedValue: T {
get { storage! }
set { storage = newValue}
}
}
Then you can even use possibly uninitialized fields storing optionals without accidentially unwrapping the optional. Something like this:
@MaybeUninitialized var x: Int?
print(x) // will crash
x = nil
print(x) // print nil
Implicitly unwrapped property warning?
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
andb?.a?.n
will both give anOptional<Int>
at the end- Ofcourse if
b
ora
isnil
thenb.a.n
will crash because it's implicitly unwrappingb
anda
to get ton
which isOptional<Int>
- To get
Int
instead ofOptional<Int>
, you would dob.a.n!
and so in your case you would do:print(residenceId!)
to getInt
I hope I made sense
Related Topics
Making a Http Post Request in Swift 2
Code Highlighting in Latex for Swift
Instance Member Cannot Be Used on Type | Closures
Searchbar Problem While Trying to Search Firestore and Reload the Tableview
How to Segue Values When My Viewcontroller Is Embedded in an Uinavigationcontroller
Shows the Alert When Uitextfield's Are Full or Empty Swift
Crop/Mask Circular Image Node in Sprite Kit Gives Jagged Edges
Retrieving an Array from Firebase
Given a Function Parameter of Type [Int]; Can It Be Constrained to Not Be Empty
Swiftui - Make Toolbar's Navigationlink Use Detail View
Swift For-In Loop with Enumerate on Custom Array2D Class
How to Move Platform with Velocity
Swift Firebase Storage How to Retrieve Image with Unknow Name(Nsuuid)
Fetch Coredata with One to Many Relationship in Swift
How to Reference the View's Window in Swift 3.X Using Storyboards/Cocoa
New' Is Unavailable: You Cannot Directly Instantiate an Stpissuingcardpin