18

When i use the following code and have nameTextField be "Jeffrey" (or any other name)

@IBAction func helloWorldAction(nameTextField: UITextField) {

    nameLabel.text = "Hello, \(nameTextField.text)"

}

nameLabel displays... Hello, Optional("Jeffrey")

But, when I change the previous code to include a "!" like this:

@IBAction func helloWorldAction(nameTextField: UITextField) {

    nameLabel.text = "Hello, \(nameTextField.text!)"

}

The code works as expected and nameLabel displays.... Hello, Jeffrey

Why is the "!" required, in the video tutorial I used to create this simple program he did not use the "!" and the program worked as expected.

Jeffrey Du Bois
  • 205
  • 3
  • 8

4 Answers4

24

Another alternative is to use the null coalescing operator within the interpolated string for prettier text without the need for if let.

nameLabel.text = "Hello, \(nameTextField.text ?? "")"

It's less readable in this case, but if there were a lot of strings it might be preferable.

Craig McMahon
  • 1,550
  • 1
  • 14
  • 36
12

Optionals must be unwrapped. You must check for it or force unwrap as you do. Imagine the optional as a box where you put a value. Before you can access it, you need to put it out.

if let name = nameTextField.text {
    nameLabel.text = "Hello, \(name)"
}
Tomáš Linhart
  • 13,509
  • 5
  • 51
  • 54
  • 27
    This seems like a terrible design choice by the creators of Swif for string interpolation. I don't know of any other language that does this. It makes way more sense to print the unwrapped value if it exists, otherwise print blank or nil. Or don't allow optionals inside of string interpolation. This has caused tons of bugs for us. – bobics Aug 26 '15 at 22:14
2

Here's a handy extension to unwrap Any? to String.

Set a default value for nil values.

extension String {
    init(_ any: Any?) {
        self = any == nil ? "My Default Value" : "\(any!)"
    }
}

// Example

let count: Int? = 3
let index: Int? = nil
String(count)
String(index)

// Output
// 3
// My Default Value
Mango
  • 187
  • 1
  • 8
Casper
  • 152
  • 12
1

You can also use optional map.
This is where I learned of how to use it.

Basically, map will take an optional and return a value if there's a value and return nil if there's no value. It think this makes more sense in code, so here's the code I found useful:

func getUserAge() -> Int? {  
    return 38  
}

let age = getUserAge()

let ageString = age.map { "Your age is \($0)" }
print(ageString ?? "We don't know your age.")

I guess this may not be super helpful in the case where you're passing in an optional string, (nil coalescing works just fine in that case), but this is super helpful for when you need to use some value that isn't a string.
It's even more useful when you want to run logic on the given value since map is a closure and you can use $0 multiple times.

Mikael Weiss
  • 839
  • 2
  • 14
  • 25