2

I am learning Swift. I came across these lines of code in a book.

import UIKit

var errorCodeString : String?  
errorCodeString = "404"  
var errorDescription : String?

if let theError = errorCodeString, 
    let errorCodeInteger = Int(theError), 
    errorCodeInteger == 404 {

    errorDescription = "\(errorCodeInteger + 200) : resource was not found." 
}

var upCaseErrorDescription = errorDescription?.uppercased()
errorDescription

upCaseErrorDescription?.append("PLEASE TRY AGAIN") 
upCaseErrorDescription

errorDescription = nil 
let description: String  
if let errorDescription = errorDescription { 
    description = errorDescription 
} else { 
    description = "NO ERROR" 
}

For this line:

if let errorDescription = errorDescription

errorDescription has been declared as a variable from the beginning and declared again as a constant.
I am a bit confused here. Are these two "errorDescription" the same?

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
Frankie
  • 185
  • 1
  • 1
  • 13
  • The optional binding introduces a new variable which happens to have the same name as the global variable. Compare https://stackoverflow.com/questions/33186448/naming-convention-for-optional-binding or https://stackoverflow.com/questions/28708986/unwrapping-swift-optional-without-variable-reassignment – Martin R May 23 '17 at 10:00
  • Possible duplicate of [What does an exclamation mark mean in the Swift language?](https://stackoverflow.com/questions/24018327/what-does-an-exclamation-mark-mean-in-the-swift-language) – Vlad Pulichev May 23 '17 at 10:01

2 Answers2

3

I am a bit confused here. Are these two "errorDescription" the same?

Actually, they are not exactly the same.

For this case, accessing errorDescription inside the block of the if let would be referred to a new -unwrapped- constant (without the ?)

if let errorDescription = errorDescription {
   print(errorDescription)
}

Prove it!

You don't need to do that anyway in your real app, it is just to make it clear to you.

If you tried to update the value of the unwrapped variable, it will not affect to original -optional- one, for example:

var myString: String? = "Hello"

if var myString = myString {
    myString += " World"
}

print(myString) // Optional("Hello")

As you can see, myString value still the same (not "Hello World").

Another way to prove that they are not the same: If you are declaring it in a class/struct, you can let the compiler to recognize between your instance variable and the unwrapped constant by using self:

struct MyStruct {
    var myString: String? = "Hello"

    func sayHello() {
        if var myString = myString {
            myString += " World" // here is the unwrapped constant ("Hello World")
            print(self.myString) // here is the instance variable ("Optional("Hello")\n")
        }
    }
}
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
1

First of all, you have to understand the concept of Optional, from Apple Docs:

A type that represents either a wrapped value or nil, the absence of a value.

So if the Optional variable has a value of that type that can be unwrapped, it contains that value. If it doesn't, it contains nil.


Let's say you have the following code:

let string: String? = "dog"

As you can see, an optional String has been created, using the optional operator ?. If you now try to print it:

print(string) 

the output will be: Optional("dog"). That is because this optional string has not been unwrapped. A way to unwrap it is using the if-let pair, as below:

if let string = string{ print(string) }

This will now output dog. But why? - When you declare a let constant in the structure of an if-statement, a copy of the original value is created, and if the value was previously nil, then the if-statement doesn't execute at all, because the condition will be false. So you are guaranteed that if the code inside the if let statement executes, then the newly-created constant will contain the successfully unwrapped value of the original variable.


"I am a bit confused here. Are these two errorDescription the same?"

No, they are not. They just happen to have the same name. You can choose any other name for the newly created constant.

Now that this things are clear, there is one more thing to be explained. When using the let constant declared in the if-condition, you refer to it as: value. When one wants to access the original optional (inside the if), it is referred as: self.value!.


There are other ways to unwrap an optional as well:

  • guard let statements - should only be used inside functions or loops

  • if value != nil{} + force-unwrapping, because you are certain that the value is not nil.


You can learn more about Optionals at The Swift Programming Language (Swift 3.1): The Basics

Mr. Xcoder
  • 4,719
  • 5
  • 26
  • 44