Related
Why would you create a "Implicitly Unwrapped Optional" vs creating just a regular variable or constant?
If you know that it can be successfully unwrapped then why create an optional in the first place?
For example, why is this:
let someString: String! = "this is the string"
going to be more useful than:
let someString: String = "this is the string"
If ”optionals indicate that a constant or variable is allowed to have 'no value'”, but “sometimes it is clear from a program’s structure that an optional will always have a value after that value is first set”, what is the point of making it an optional in the first place?
If you know an optional is always going to have a value, doesn't that make it not optional?
Before I can describe the use cases for Implicitly Unwrapped Optionals, you should already understand what Optionals and Implicitly Unwrapped Optionals are in Swift. If you do not, I recommend you first read my article on optionals
When To Use An Implicitly Unwrapped Optional
There are two main reasons that one would create an Implicitly Unwrapped Optional. All have to do with defining a variable that will never be accessed when nil because otherwise, the Swift compiler will always force you to explicitly unwrap an Optional.
1. A Constant That Cannot Be Defined During Initialization
Every member constant must have a value by the time initialization is complete. Sometimes, a constant cannot be initialized with its correct value during initialization, but it can still be guaranteed to have a value before being accessed.
Using an Optional variable gets around this issue because an Optional is automatically initialized with nil and the value it will eventually contain will still be immutable. However, it can be a pain to be constantly unwrapping a variable that you know for sure is not nil. Implicitly Unwrapped Optionals achieve the same benefits as an Optional with the added benefit that one does not have to explicitly unwrap it everywhere.
A great example of this is when a member variable cannot be initialized in a UIView subclass until the view is loaded:
class MyView: UIView {
#IBOutlet var button: UIButton!
var buttonOriginalWidth: CGFloat!
override func awakeFromNib() {
self.buttonOriginalWidth = self.button.frame.size.width
}
}
Here, you cannot calculate the original width of the button until the view loads, but you know that awakeFromNib will be called before any other method on the view (other than initialization). Instead of forcing the value to be explicitly unwrapped pointlessly all over your class, you can declare it as an Implicitly Unwrapped Optional.
2. When Your App Cannot Recover From a Variable Being nil
This should be extremely rare, but if your app can not continue to run if a variable is nil when accessed, it would be a waste of time to bother testing it for nil. Normally if you have a condition that must absolutely be true for your app to continue running, you would use an assert. An Implicitly Unwrapped Optional has an assert for nil built right into it. Even then, it is often good to unwrap the optional and use a more descriptive assert if it is nil.
When Not To Use An Implicitly Unwrapped Optional
1. Lazily Calculated Member Variables
Sometimes you have a member variable that should never be nil, but it cannot be set to the correct value during initialization. One solution is to use an Implicitly Unwrapped Optional, but a better way is to use a lazy variable:
class FileSystemItem {
}
class Directory : FileSystemItem {
lazy var contents : [FileSystemItem] = {
var loadedContents = [FileSystemItem]()
// load contents and append to loadedContents
return loadedContents
}()
}
Now, the member variable contents is not initialized until the first time it is accessed. This gives the class a chance to get into the correct state before calculating the initial value.
Note: This may seem to contradict #1 from above. However, there is an important distinction to be made. The buttonOriginalWidth above must be set during viewDidLoad to prevent anyone changing the buttons width before the property is accessed.
2. Everywhere Else
For the most part, Implicitly Unwrapped Optionals should be avoided because if used mistakenly, your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn't hurt very much.
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.
Implicitly unwrapped optionals are useful for presenting a property as non-optional when really it needs to be optional under the covers. This is often necessary for "tying the knot" between two related objects that each need a reference to the other. It makes sense when neither reference is actually optional, but one of them needs to be nil while the pair is being initialized.
For example:
// These classes are buddies that never go anywhere without each other
class B {
var name : String
weak var myBuddyA : A!
init(name : String) {
self.name = name
}
}
class A {
var name : String
var myBuddyB : B
init(name : String) {
self.name = name
myBuddyB = B(name:"\(name)'s buddy B")
myBuddyB.myBuddyA = self
}
}
var a = A(name:"Big A")
println(a.myBuddyB.name) // prints "Big A's buddy B"
Any B instance should always have a valid myBuddyA reference, so we don't want to make the user treat it as optional, but we need it to be optional so that we can construct a B before we have an A to refer to.
HOWEVER! This sort of mutual reference requirement is often an indication of tight coupling and poor design. If you find yourself relying on implicitly unwrapped optionals you should probably consider refactoring to eliminate the cross-dependencies.
Implicitly unwrapped optionals are pragmatic compromise to make the work in hybrid environment that has to interoperate with existing Cocoa frameworks and their conventions more pleasant, while also allowing for stepwise migration into safer programing paradigm — without null pointers — enforced by the Swift compiler.
Swift book, in The Basics chapter, section Implicitly Unwrapped Optionals says:
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.
…
You can think of an implicitly unwrapped optional as giving permission for the optional to be unwrapped automatically whenever it is used. Rather than placing an exclamation mark after the optional’s name each time you use it, you place an exclamation mark after the optional’s type when you declare it.
This comes down to use cases where the non-nil-ness of properties is established via usage convention, and can not be enforced by compiler during the class initialization. For example, the UIViewController properties that are initialized from NIBs or Storyboards, where the initialization is split into separate phases, but after the viewDidLoad() you can assume that properties generally exist. Otherwise, in order to satisfy the compiler, you had to be using the
forced unwrapping,
optional binding
or optional chaining
only to obscure the main purpose of the code.
Above part from the Swift book refers also to the Automatic Reference Counting chapter:
However, there is a third scenario, in which both properties should always have a value, and neither property should ever be nil once initialization is complete. In this scenario, it is useful to combine an unowned property on one class with an implicitly unwrapped optional property on the other class.
This enables both properties to be accessed directly (without optional unwrapping) once initialization is complete, while still avoiding a reference cycle.
This comes down to the quirks of not being a garbage collected language, therefore the breaking of retain cycles is on you as a programmer and implicitly unwrapped optionals are a tool to hide this quirk.
That covers the “When to use implicitly unwrapped optionals in your code?” question. As an application developer, you’ll mostly encounter them in method signatures of libraries written in Objective-C, which doesn’t have the ability to express optional types.
From Using Swift with Cocoa and Objective-C, section Working with nil:
Because Objective-C does not make any guarantees that an object is non-nil, Swift makes all classes in argument types and return types optional in imported Objective-C APIs. Before you use an Objective-C object, you should check to ensure that it is not missing.
In some cases, you might be absolutely certain that an Objective-C method or property never returns a nil object reference. To make objects in this special scenario more convenient to work with, Swift imports object types as implicitly unwrapped optionals. Implicitly unwrapped optional types include all of the safety features of optional types. In addition, you can access the value directly without checking for nil or unwrapping it yourself. When you access the value in this kind of optional type without safely unwrapping it first, the implicitly unwrapped optional checks whether the value is missing. If the value is missing, a runtime error occurs. As a result, you should always check and unwrap an implicitly unwrapped optional yourself, unless you are sure that the value cannot be missing.
...and beyond here lay
One-line (or several-line) simple examples don't cover the behavior of optionals very well — yeah, if you declare a variable and provide it with a value right away, there's no point in an optional.
The best case I've seen so far is setup that happens after object initialization, followed by use that's "guaranteed" to follow that setup, e.g. in a view controller:
class MyViewController: UIViewController {
var screenSize: CGSize?
override func viewDidLoad {
super.viewDidLoad()
screenSize = view.frame.size
}
#IBAction printSize(sender: UIButton) {
println("Screen size: \(screenSize!)")
}
}
We know printSize will be called after the view is loaded — it's an action method hooked up to a control inside that view, and we made sure not to call it otherwise. So we can save ourselves some optional-checking/binding with the !. Swift can't recognize that guarantee (at least until Apple solves the halting problem), so you tell the compiler it exists.
This breaks type safety to some degree, though. Anyplace you have an implicitly unwrapped optional is a place your app can crash if your "guarantee" doesn't always hold, so it's a feature to use sparingly. Besides, using ! all the time makes it sound like you're yelling, and nobody likes that.
Apple gives a great example in The Swift Programming Language -> Automatic Reference Counting -> Resolving Strong Reference Cycles Between Class Instances -> Unowned References and Implicitly Unwrapped Optional Properties
class Country {
let name: String
var capitalCity: City! // Apple finally correct this line until 2.0 Prerelease (let -> var)
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
The initializer for City is called from within the initializer for Country. However, the initializer for Country cannot pass self to the City initializer until a new Country instance is fully initialized, as described in Two-Phase Initialization.
To cope with this requirement, you declare the capitalCity property of Country as an implicitly unwrapped optional property.
The rationale of implicit optionals is easier to explain by first looking at the rationale for forced unwrapping.
Forced unwrapping of an optional (implicit or not), using the ! operator, means you're certain that your code has no bugs and the optional already has a value where it is being unwrapped. Without the ! operator, you would probably just assert with an optional binding:
if let value = optionalWhichTotallyHasAValue {
println("\(value)")
} else {
assert(false)
}
which is not as nice as
println("\(value!)")
Now, implicit optionals let you express having an optional which you expect to always to have a value when unwrapped, in all possible flows. So it just goes a step further in helping you - by relaxing the requirement of writing the ! to unwrap each time, and ensuring that the runtime will still error in case your assumptions about the flow are wrong.
If you know for sure, a value return from an optional instead of nil, Implicitly Unwrapped Optionals use to directly catch those values from optionals and non optionals can't.
//Optional string with a value
let optionalString: String? = "This is an optional String"
//Declaration of an Implicitly Unwrapped Optional String
let implicitlyUnwrappedOptionalString: String!
//Declaration of a non Optional String
let nonOptionalString: String
//Here you can catch the value of an optional
implicitlyUnwrappedOptionalString = optionalString
//Here you can't catch the value of an optional and this will cause an error
nonOptionalString = optionalString
So this is the difference between use of
let someString : String! and let someString : String
Implicitly Unwrapped Optional(IUO)
It is a syntactic sugar for Optional that does not force a programmer to unwrap a variable. It can be used for a variable which can not be initialised during two-phase initialization process and implies non-nil. This variable behaves itself as non-nil but actually is an optional variable. A good example is - Interface Builder's outlets
Optional usually are preferable
var implicitlyUnwrappedOptional: String! //<- Implicitly Unwrapped Optional
var nonNil: String = ""
var optional: String?
func foo() {
//get a value
nonNil.count
optional?.count
//Danderour - makes a force unwrapping which can throw a runtime error
implicitlyUnwrappedOptional.count
//assign to nil
// nonNil = nil //Compile error - 'nil' cannot be assigned to type 'String'
optional = nil
implicitlyUnwrappedOptional = nil
}
I think Optional is a bad name for this construct that confuses a lot of beginners.
Other languages (Kotlin and C# for example) use the term Nullable, and it makes it a lot easier to understand this.
Nullable means you can assign a null value to a variable of this type. So if it's Nullable<SomeClassType>, you can assign nulls to it, if it's just SomeClassType, you can't. That's just how Swift works.
Why use them? Well, sometimes you need to have nulls, that's why. For example, when you know that you want to have a field in a class, but you can't assign it to anything when you are creating an instance of that class, but you will later on. I won't give examples, because people have already provided them on here. I'm just writing this up to give my 2 cents.
Btw, I suggest you look at how this works in other languages, like Kotlin and C#.
Here's a link explaining this feature in Kotlin:
https://kotlinlang.org/docs/reference/null-safety.html
Other languages, like Java and Scala do have Optionals, but they work differently from Optionals in Swift, because Java and Scala's types are all nullable by default.
All in all, I think that this feature should have been named Nullable in Swift, and not Optional...
I was trying to assign a value to a var but I get this error: fatal error: unexpectedly found nil while unwrapping an Optional value.
the code:
vehicle.chassis = Chasis.text
but the variable is not an optional, I declare the variable this way:
var vehicle: Vehicle!
how can I fix this problem?
check the image
You are trying to set a property to an instance that doesn't exist, because the implicitly unwrapped Optional vehicle is nil.
You can't set vehicle.chassis if vehicle is nil.
Before accessing .chassis you have to populate vehicle somewhere with an instance of Vehicle, for example in an init, or in viewDidLoad, etc:
vehicle = Vehicle()
and then you can access the .chassis property:
vehicle.chassis = Chasis.text
To clarify what some of the above commenters have already mentioned, you're declaring your property as an Implicitly Unwrapped Optional (IUO herein). Only optionals in Swift can be nil, but optionals must be unwrapped, IUO's don't need to be unwrapped, but might crash. IUO's exist for 2 reasons.
To provide an unsafe/more raw access to your property to achieve ingrained Objective-C design patterns more quickly. That is, directly act on "pointers" that may or may not be nil and crash when it is.
To provide a non-optional interface to properties that you cannot guarantee will be initialized by the time your class/struct init finishes, but you can guarantee will be initialized by the time you use it. Useful for something the compiler can't verify but you as a programmer can.
That being said, I can only think of 2 sane proper ways to use IUO's in a Swifty manner, 1 is for IBOutlets, these aren't compiled by the swift compiler, don't exist after init(), but are guaranteed to be fulfilled by the time you use it (if your nib isn't corrupt), perfect use case for IUO's.
Another, while less imperative since it can be designed around, is Database models where you want lazy reads (which in itself is a bit of a pain to implement anyway)
I'm trying to wrap my head around why what feels intuitive is illegal when it comes to a dictionary containing an array in Swift.
Suppose I have:
var arr = [1,2,3,4,5]
var dict = ["a":1, "b":2, "test":arr]
I can easily access the dictionary members like so:
dict["a"]
dict["b"]
dict["test"]
As expected, each of these will return the stored value, including the array for key "test":
[1,2,3,4,5]
My intuitive reaction to this based on other languages is that this should be legal:
dict["test"][2]
Which I would expect to return 3. Of course, this doesn't work in Swift. After lots of tinkering I realize that this is the proper way to do this:
dict["test"]!.objectAtIndex(2)
Realizing this, I return to my intuitive approach and say, "Well then, this should work too:"
dict["test"]![2]
Which it does... What I don't really get is why the unwrap isn't implied by the array dereference. What am I missing in the way that Swift "thinks?"
All dictionary lookups in Swift return Optional variables.
Why? Because the key you are looking up might not exist. If the key doesn't exist, the dictionary returns nil. Since nil can be returned, the lookup type has to be an Optional.
Because the dictionary lookup returns an Optional value, you must unwrap it. This can be done in various ways. A safe way to deal with this is to use Optional Chaining combined with Optional Binding:
if let value = dict["test"]?[2] {
print(value)
}
In this case, if "test" is not a valid key, the entire chain dict["test"]?[2] will return nil and the Optional Binding if let will fail so the print will never happen.
If you force unwrap the dictionary access, it will crash if the key does not exist:
dict["test"]![2] // this will crash if "test" is not a valid key
The problem is that Dictionary’s key-based subscript returns an optional – because the key might not be present.
The easiest way to achieve your goal is via optional chaining. This compiles:
dict["test"]?[2]
Note, though, that the result will still be optional (i.e. if there were no key test, then you could get nil back and the second subscript will not be run). So you may still have to unwrap it later. But it differs from ! in that if the value isn’t present your program won’t crash, but rather just evaluate nil for the optional result.
See here for a long list of ways to handle optionals, or here for a bit more background on optionals.
In the Objective-C world, it has potential crash if you are trying to access 3 by dict[#"test"][2]. What if dict[#"test"] is nil or the array you get from dict[#"test"] has two elements only? Of course, you already knew the data is just like that. Then, it has no problem at all.
What if the data is fetched from the backend and it has some problems with it? This will still go through the compiler but the application crashes at runtime. Users are not programmers and they only know: The app crashes. Probably, they don't want to use it anymore. So, the bottom line is: No Crashes at all.
Swift introduces a type called Optional Type which means value might be missing so that the codes are safe at runtime. Inside the Swift, it's actually trying to implement an if-else to examine whether data is missing.
For your case, I will separate two parts:
Part 1: dict["test"]! is telling compiler to ignore if-else statement and return the value no matter what. Instead, dict["test"]? will return nil if the value if missing. The terminology is Explicit Unwrapping
Part 2: dict["test"]?[2] has potential crash. What if dict["test"]? returns a valid array and it only has two element? This way to store the data is the same using dict[#"test"][2] in Objective-C. That's why it has something called Optional Type Unwrapping. It will only go the if branch when valid data is there. The safest way:
if let element = dict["test"]?[2] {
// do your stuff
}
I've been playing around with Swift and discovered that when down casting an object to be inserted into a dictionary, I get a weird warning: Treating a forced downcast to 'String' as optional will never produce 'nil'. If I replace as with as? then the warning goes away.
func test() -> AnyObject! {
return "Hi!"
}
var dict = Dictionary<String,String>()
dict["test"]=test() as String
Apple's documentation says the following
Because downcasting can fail, the type cast operator comes in two different forms. The optional form, as?, returns an optional value of the type you are trying to downcast to. The forced form, as, attempts the downcast and force-unwraps the result as a single compound action.
I'm unclear as to why using as? instead of as is correct here. Some testing reveals that if I change test() to return an Int instead of a String, the code will quit with an error if I continue using as. If I switch to using as? then the code will continue execution normally and skip that statement (dict will remain empty). However, I'm not sure why this is preferable. In my opinion, I would rather the program quit with an error and let me know that the cast was unsuccessful then simply ignore the erroneous statement and keep executing.
According to the documentation, I should use the forced form "only when you are sure that the downcast will always succeed." In this case I am sure that the downcast will always succeed since I know test() can only return a String so I would assume this is a perfect situation for the forced form of down casting. So why is the compiler giving me a warning?
Let's take a closer look at your last line, and explode it to see what's happening:
let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString
The error is on the second line, where you are telling the compiler to enforce that temporaryAnyObject is definitely a String. The code will still compile (assuming you don't treat warnings as errors), but will crash if temporaryAnyObject is not actually a String.
The way as works, with no ?, is basically saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise we've become inconsistent and can no longer run.
The way as? works (with the ?) is saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise the result of this expression is nil.
So in my exploded example above, if test() does return a String, then the as downcast succeeds, and temporaryString is now a String. If test() doesn't return a String, but say an Int or anything else not subclassed from String, then the as fails and the code can no longer continue to run.
This is because, as the developer in complete control, you told the system to behave this way by not putting the optional ? indicator. The as command specifically means that you do not tolerate optional behavior and you require that downcast to work.
If you had put the ?, then temporaryString would be nil, and the third line would simple remove the "test" key/value pair from the dictionary.
This might seem strange, but that's only because this is the opposite default behavior of many languages, like Obj-C, which treat everything as optional by default, and rely on you to place your own checks and asserts.
Edit - Swift 2 Update
Since Swift 2, the forced, failable downcast operator as has been removed, and is replaced with as!, which is much Swiftier. The behavior is the same.
You can solve this warning from two angles. 1. The value you return 2. The type that you are expected to return. The other answer speaks about the 1st angle. I'm speaking about the 2nd angle
This is because you are returning a forced unwrapped and casted value for an optional. The compiler is like, "If you really want to just force cast all optionals then why not just make the expected return parameter to be a non-optional"
For example if you wrote
func returnSomething<T> -> T?{ // I'm an optional, I can handle nils SAFELY and won't crash.
return UIViewController as! T // will never return a safe nil, will just CRASH
}
Basically you told yourself (and the compiler) I want to handle nils safely but then in the very next line, you said nah, I don't!!!
The compiler would give a warning:
Treating a forced downcast to 'T' as optional will never produce 'nil'
An alternative is to remove the ?
func returnSomething<T>() -> T{ // I can't handle nils
return UIViewController() as! T // I will crash on nils
}
Having that said, likely the best way is to not use force cast and just do:
func returnSomething<T>() -> T?{ // I can handle nils
return UIViewController() as? T // I won't crash on nils
}
It looks like there is bug open about this warning fo some years now...
https://bugs.swift.org/browse/SR-4209 So it shows even in situations where it is obvious what you are doing and right.
The NSMetadataItem class in the Cocoa framework under Swift contains the following function:
func valueForAttribute(key: String!) -> AnyObject!
I'm still learning the difference (and details) between forced unwrapping and optional chaining. In the above function, does this mean:
The key parameter must have a value, and
The return value is guaranteed to have a value?
My primary concern is with the exclamation point following the return value - once I have assigned the return value:
var isDownloadedVal = item.valueForAttribute(NSMetadataUbiquitousItemIsDownloadedKey)
Do I need to include an if let block when examining it, or am I guaranteed that it will have a value I can examine safely?
TLDR: Treat Foo! as if it were Foo.
Many Cocoa calls include implicitly unwrapped optionals, and their need for it is very likely the reason the feature even exists. Here's how I recommend thinking about it.
First, let's think about a simpler case that doesn't involve AnyObject. I think UIDevice makes a good example.
class func currentDevice() -> UIDevice!
What's going on here? Well, there is always a currentDevice. If this returned nil that would indicate some kind of deep error in the system. So if we were building this interface in Swift, this would likely just return UIDevice and be done with it. But we need to bridge to Objective-C, which returns UIDevice*. Now that should never be nil, but it syntactically could be nil. Now in ObjC, we typically ignore that fact and don't nil-check here (particularly because nil-messaging is typically safe).
So how would we express this situation in Swift? Well, technically it's an Optional<UIDevice>, and you'd wind up with:
class func currentDevice() -> UIDevice?
And you'd need to explicitly unwrap that every time you used it (ideally with an if let block). That would very quickly drive you insane, and for nothing. currentDevice() always returns a value. The Optional is an artifact of bridging to ObjC.
So they invented a hack to work around that (and I think it really is a hack; I can't imagine building this feature if ObjC weren't in the mix). That hack says, yes, it's an Optional, but you can pretend it's not, and we promise it's always going to be a value.
And that's !. For this kind of stuff, you basically ignore the ! and pretend that it's handing you back a UIDevice and roll along. If they lied to you and return nil, well, that's going to crash. They shouldn't have lied to you.
This suggests a rule: don't use ! unless you really need to (and you pretty much only need to when bridging to ObjC).
In your specific example, this works in both directions:
func valueForAttribute(key: String!) -> AnyObject!
Technically it takes an Optional<String>, but only because it's bridged to NSString*. You must pass non-nil here. And it technically returns you Optional<AnyObject>, but only because it's bridged to id. It promises that it won't be nil.
According to the Swift-eBook, which states the following
„Trying to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value.“
I would answer to your first two questions with Yes.
Do I need to include an if let block when examining it...
No, this is not necessary.