When and Why are Swift optionals particularly confusing to beginners? | various ways to unwrap an optional in Swift Programming

optional binding swift,optional chaining in swift,swift optional chaining,optional binding and optional chaining,swift optional,optional chaining,swiftapp

This topic is very confusing for the learner. I think you're confused about its format and why Swift has it. 
Swift Optional is a very important underlying concept in Swift programming. Optional is something that you are doing a lot of work with in developing Swift Code.

An optional is a variable which will become nil over the lifetime of that object. Nil is just a type-safe indicator for "no value" or "empty".

Optional allow you to write flexible and more safe code,Question mark (?) means it can be nil or some value.

Optionals introduce a high level of type-safety in Swift code. Additionally, nil is that the only value that safely denotes "no value" in Swift code. Objective-C had nil, NSNull and NULL. Optionals are often checked at compile-time (as against run-time) and is therefore type-safe. A programmer can check the tactic signature, see that it returns an optional and thus understands that the tactic could fail. Such a thing wasn't clear in Objective-C. Also, optional casting (with "as?") allows a cast from one type to another to fail.

Swift Programming introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Using optionals is similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Not only are optionals safer and more expressive than nil pointers in Objective-C, they’re at the heart of many of Swift’s most powerful features. e.g

struct Person { 
	var title: String? 
	var name: String! 

There are two variables within the struct — the title and name. they're both String types. However, title are often nil for a person, while name cannot — a person is guaranteed to have a name. For the title, we call it optional.

You see here Swift introduces the optional concept to make sure you want to decide whether a variable has a value or not; thus increasing the security of the entire codebase.

And Swift uses question mark and exclamation point to separate a nullable and non-nullable value, which is clear and readable from my perspective.

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.
  • When a method that's supposed to return a value fails. An optional is returned to enforce checking against nil.
  • When you want to use a method, but don't want to provide certain arguments. If those are optional, you can just pass nil.

Ways to Unwrap Optionals in Swift

A- Forced unwrapping 

If you defined a variable as optional, then to get the value from this variable, you will have to unwrap it. This just means putting an exclamation mark at the end of the variable.

        var myString:String?
        myString = "Hii, AppCodeZip!"
        let obj = myString!     // forced unwrapping Success!!!
        print(obj)           // Hii, AppCodeZip!

let nickName:String?
        let name = nickName!    //The value is not set.
        print(name)             // forced unwrapping Error. (Constant 'nickName' used before being initialized)

B- Implicit unwrapping 

Implicitly unwrapped optionals are optionals that don't behave like optionals. You declare them with a ‘!’ following the type. They are then an optional, but wherever it is used they will automatically be forced unwrapped, so are used just like regular non-optional types.

// Implicitly unwrapped optional
        var example:String! = nil
        test(example) // Runtime error, not compiler error
        example = "Hello"
        // no exclamation needed, it's implicit
        test(example) // "Hello"

Test for nil before force unwrapping it:
you check if a variable has a value or not by:

if tweet !=nil {
 println(tweet is not nil)
} else {
 println(tweet is nil)

C- Optional Binding

Swift introduces Optional Binding to do the same exact checking:

if let actualTweet = tweet {
 println(The value is: \(actualTweet))
} else {
 println(Gracefully go to this line when tweet is nil)

In the Optional Binding example, the tweet is checked if it has a value. If it has a value, we will implicitly unwrap and assign tweet to equal actualTweet as a temporary constant. This temporary constant can now be used in the conditional block. If tweet = nil, go to the else statement. This forgoes the need to use the “!” since the value was copied over to the new variable.

D- nil coalesing operator

The ?? (nil coalescing operator) instruction can be used to supply a default value to be used when the optional is nil.
As an example, here’s some code we wrote earlier that prints of two strings:

let name: String? = "AppCodeZip"

if let unwrappedName = name {
    print("Hello, \(unwrappedName)!")
} else {
    print("Hello, anonymous!")

Using nil coalescing we could collapse that down to just two lines:

let unwrappedName = name ?? "anonymous"
print("Hello, \(unwrappedName)")

E. Optional Chaining

Optional chaining looks simple but is deceptively powerful. You simply use a ? when referencing optional values.

Let’s look at a simple example with a person and optional address (which also has an optional postcode).

class Person { 
	var name: String 
	var address: Address? 
	init(name: String) { self.name = name } 
class Address { 
	var streetReference: String 
	var postCode: String? 
	init(streetReference: String) { 
		self.streetReference = streetReference 
let andy = Person(name: "Andy") 
let streetRef = andy.address?.streetReference // chaining 
let streetRef2 = andy.address!.streetReference // forced unwrapping  

address is an optional Address, Address?, and hasn't been supplied here so the assignment of streetRef will fail (but not the program) at the address segment.

With optional chaining, by using ?, streetRef will be defined as an optional String, String?, because Address.streetReference is a String.

When any type is referenced by optional chaining the value returned is an Optional version of that type.

streetRef2 however, will be a String, because Address.streetReference is a String and is being accessed directly by forced unwrapping.

In this example, because address is not set, both assignments will fail, however, streetRef will be assigned nil and the program will continue, whereas the program will crash once it tries to assign streetRef2 because forced unwrapping will encounter the nil in address.

With optional chaining, multiple values can be optionals.

let postCode = andy.address?.postCode? 

Again, postCode will be an optional String, String?. Note, that Address.postCode is already defined as String?. In this case the assigned type does not become an optional optional, one level of optionality is sufficient, so it remains String?.

Typically, you might combine optional chaining with ‘if let’:

if let postCode = andy.address?.postCode? { 

Optional chaining can also be used on the assigned value, for example:

andy.address?.postCode = "ABC 123" 

In this scenario, if address is set, then the postCode will be set to “ABC 123”. If address is not set, then the assignment won't happen.

However, note again that this is a silent failure, you don't get any feedback on whether the assignment happened.

So this might be a scenario to make use of nil comparison:

if (andy.address?.postCode = "ABC 123") != nil { 
	print("Post Code was changed") 
} else { 
	print("Post Code was NOT changed") 

The reason this works is because assignments have an implicit return type of Void and when optional chaining is used that return type becomes an optional Void, Void? and so it can be tested for nil.

F. Guard let.

It’s probably also worth mentioning the guard statement. The guard statement is a safety feature that can be used independently of optionals and probably deserves a whole topic to itself, but one thing it supports is an alternative form of optional binding and so it’s worth taking a quick look at that:

func updatePostCode(address: Address?, postCode: String?) { 
	guard let validAddress = address else { return } 
	guard let validPostCode = postCode else { return } 
	validAddress.postCode = validPostCode 

The unusual behaviour of guard of is that while it looks like an if let statement, the bound variables scope rules are different and it also requires an else block which must explicitly state where to transfer control if the assignment or test fails.

The bound optionals specified in the guard statement (validAddress and validPostCode in this example) are available in the same scope where the guard statement is written, which in this example means the scope of the function updatePostCode(: Address?, :String?). This means the valid bound versions of the variables are then available for use in the function. This seems a bit weird at first, but it’s a very useful feature.


Similar solutions you may also like...


Post a Comment