The Joys of Beta Swift: More with Optionals and the “does not have a member named” error

We’ve had another change to the Swift compiler that was brought to my attention by an astute reader. I was aware of it, and you’ll notice I even used it in the last few posts, but I really should have warned people about it, and got it fixed.

Back in my post on Adding an MVC Model Class in Swift There is an error one reader some issues with. The code in question reads:

@IBOutlet var resultsDisplayLabel : UILabel!
@IBAction func sizeButton(sender : UIButton) {
        pizza.pizzaDiameter = pizza.diameterFromString(sender.titleLabel.text)
        displayPizza()
    }

On the GM seed of Xcode 6, this give the error:

'UILabel?' does not have a member named 'text'

You might be one of those people who goes back to the class reference by option clicking on the keyword UILabel in the outlet,  then clicking the class reference link(or hitting command-shift-0 and searching for UILabel). You’d find that indeed UILabel has a property named text. You might even want to get very frustrated — until you read farther. It’s that little question mark that is the issue. The UIButton property titleLabel is an optional of type UILabel, and you have to unwrap the optional before you can use the property text. When you get that message, first thing to check is if you’re dealing with an optional, which will show up in the type at the beginning of the error message. In this case, we have an optional since it is UILabel? If an optional value, you need to unwrap it. So the code should read:

@IBOutlet var resultsDisplayLabel : UILabel!
@IBAction func sizeButton(sender : UIButton) {
        pizza.pizzaDiameter = pizza.diameterFromString(sender.titleLabel!.text)
        displayPizza()
    }

I force unwrap it without checking if it is nil. If nil, I will get a run time error. The titlelabel should have a value. If not,  I didn’t connect it to the label, and I want to know that.

That should solve the problem…

…but now we get…
Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
The String type in text is also an optional.  We need to force unwrap text too.

@IBOutlet var resultsDisplayLabel : UILabel!
@IBAction func sizeButton(sender : UIButton) {
        pizza.pizzaDiameter = pizza.diameterFromString(sender.titleLabel!.text!)
        displayPizza()
    }

Anthere problem I’ve run tinto is that optioanls cannot be directly evaluated as a boolean value. Therefore everywhere that is
if myOptional{do someting}
must be
if (myOptional != nil) {do something}.
Fortunately Xcode will tel you this and ask you if you want Xcode to fix it for you.

So if you get those messages you know what to do. I fixed the MVC model post and both delegates posts. I am working on the table post. Some of my old code still doesn’t work and I’ll go back and fix it very shortly. Any more you find, please let me know so I can get the code updated to the current version.

Apple is making a lot of API into explicit optionals to keep things consistent. I’m hoping by the production release we don’t ever have too many more changes like this.

One Reply to “The Joys of Beta Swift: More with Optionals and the “does not have a member named” error”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s