Reputation: 29094
When I write a simple function such as this:
@IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel.text);
}
It gives me an error: UILabel doesn't have a label called text.
However, when I change it to this:
@IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel?.text);
}
It works fine, but it prints out something like this:
Optional("1");
What I am doing wrong? I am expecting a value of 1. But it is printing out Optional("1") and secondly, it is working fine when println(theButton.titleLabel?.text);
Upvotes: 0
Views: 1711
Reputation: 27345
Optional chaining makes the result optional, so you are printing optional value: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/OptionalChaining.html
With optional binding you can print the value only if it exits.
if let text = theButton.titleLabel?.text {
println(text)
} else {
// text doesn't have value
}
Upvotes: 2
Reputation: 72770
@Kirsteins's answer shows how to obtain the button label text in a safe manner.
Remember that:
UIButton
has a titleLabel
, which is an optional UILabel
.UILabel
has a text
property, which is an optional String
so there are 2 optionals in the chain. You can use optional binding as in @Kirsteins's answer, or use forced unwrapping:
let text = theButton.titleLabel!.text!
which however I discourage using, because if any of the 2 is nil you'll have a runtime exception. But for completeness it's worth mentioning.
Upvotes: 2
Reputation: 3773
Kirsteins answers it correctly but misses one small detail
if your object can be nil (optional) you need to check first if it exists to then access its value, like this:
if let text = theButton.titleLabel?.text {
println(text)
}
but you can also ignore the if and just call it like this:
let text : String = theButton.titleLabel?.text
// If theButton.titleLabel don't exists then text will be nil
this happen if the IBOutlet was declared with ?
but if you declare with !
that means you know that it could be nil, but you never want it to be nil, for a IBOutlet i prefer this approach since if the IBOutlet is not connected then maybe something is worn with my code.
@IBOutlet var theButton : UIButton!
// and get text value as
theButton.titleLabel!.text
this will ensure theButton.titleLabel could be nil, but in this part of code it is required, hope this helps to understand the difference between optional (?
) and optional required (!
)
Upvotes: 0
Reputation: 6669
The buttons titleLabel property returns an optional UILabel, that means it's possible that the button doesn't have a titleLabel.
var titleLabel: UILabel? { get }
If you don't set a title to the button, then the button doesn't have a titleLabel property, the iOS framework adds the titleLabel only if the button has a title, I think this happens to reduce memory.
This is why you have to put the "?" (is called optional chaining you can read about it here http://bit.ly/1vrSOi1) in that line, but this usually get auto completed by Xcode itself.
Upvotes: 0