2

I am learning Swift and hacking around in a playground. I have the following Dictionary:

var person = [
    "first": "John",
    "last": "Smith",
    "age": 21
]

I am using the following line to print output:

"Your first name is \(person["first"]) and you are \(person["age"]) years old."

With this code, I get the following output:

// -> "Your first name is Optional(John) and you are Optional(21) years old."

I expected to receive the following as output:

// -> "Your first name is John and you are 21 years old."

Where is the Optional coming from? Why doesn't this simply print the value at the specified key? What do I need to do to fix this?

otolock
  • 662
  • 7
  • 23
  • 5
    You should really read the language guide, which covers Optionals, Dictionaries, and other language basics in great detail. – Alexander Aug 17 '16 at 19:47
  • @AlexanderMomchliov I have it downloaded, however I am currently reading this https://www.hackingwithswift.com/ for a quick breakdown of the language and the start the language guide. – otolock Aug 17 '16 at 19:49
  • This has been asked and answered repeatedly. Just search for `[swift] print optional` – Martin R Aug 17 '16 at 19:55
  • @tymac I spent 30 minutes searching on SO for this plus read all of the suggested articles when I finished writing. I feel like I did my due diligence to search before asking. – otolock Aug 17 '16 at 22:17
  • I know so do I every time :) lol I feel your pain. – Edison Aug 17 '16 at 22:18

3 Answers3

5

Retrieving a value for a given key from a dictionary is always an optional because the key might not exist then the value is nil. Using String Interpolation "\(...)" the Optional is included as literal string.

To avoid the literal Optional(...) in String Interpolation you have to unwrap the optionals preferred in a safe way

if let first = person["first"] as? String, age = person["age"] as? Int {
   print("Your first name is \(first) and you are \(age) years old.")
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • 2
    The null coalescing operator `??` can also be handy here, to provide a default value in case the property is `nil`. e.g. `print("Your first name is \(person["first"] ?? "unknown") and you are \(person["age"] ?? "an unknown number of") years old.")` – Jesse Amano Aug 17 '16 at 19:47
  • 1
    Indeed, but in real life any person is supposed to have a first name and an age (I know that defeats the suggestion to use optional bindings) ;-) – vadian Aug 17 '16 at 19:55
  • @JesseAmano's solution also works, but only if `age` is saved as a `String`, if it remains as an `Int`, the `Optional` remains. – otolock Aug 17 '16 at 19:58
  • 1
    I definitely agree; I also think using `!` anywhere crashing the app wouldn't be desired behavior (so loading image assets and binding to storyboards might be exceptions) is a really bad idea, on par with `if expressionThatIsProbablyAlwaysTrue() { alwaysDoThis(); } else { presentAlert("lolz u'll never c this!!1!") }`. So I figured I'd add on that `??` is an alternative for anyone who thinks using `if` and `guard` to unwrap optional values is too verbose/bureaucratic (or some other gripe) – Jesse Amano Aug 17 '16 at 20:00
1

Your string has not been unwrapped and is an optional that is why you see the word optional and the parenthesis. If you want them to go away you can put an ! to unwrap it. However, I would suggest handling it differently so you don't try to unwrap a nil value.

For example,

var person = [
"first": "John",
"last": "Smith",
"age": 21
]

print("Your first name is \(person["first"]) and you are \(person["age"]) years old.")
// prints: "Your first name is Optional(John) and you are Optional(21) years old."

print("Your first name is \(person["first"]!) and you are \(person["age"]!) years old.")
// prints: "Your first name is John and you are 21 years old."

let name = person["first"]!
let age = person["age"]!
print("Your first name is \(name) and you are \(age) years old.")
// prints: "Your first name is John and you are 21 years old."

Vadian has a great example of how to properly print this out as his example will not crash if you get something that is nil.

Jonah Starling
  • 539
  • 6
  • 20
-1

Try to make it like this

"Your first name is \(person["first"]!) and you are \(person["age"]!) years old."

And then try to take a look at the perfect explanation here Printing optional variable

Community
  • 1
  • 1
jonask
  • 679
  • 2
  • 6
  • 21