1

I have a standard UIButton in a standard single view project. I want to get the text of the button when it is clicked. However, in Xcode 7.0 GM I am getting strange behavior with the compiler requiring me to use ??, ?!, or !!. When trying to unwrap the text there is more strange behavior: only triple unwrapping finally does it.

@IBAction func buttonTapped(sender: AnyObject) {

    print( sender.titleLabel?!.text ) // Optional("Button")
    print( sender.titleLabel??.text ) // Optional("Button")
    print( sender.titleLabel!!.text ) // Optional("Button")

    print( sender.titleLabel?!.text! ) // Optional("Button")
    print( sender.titleLabel??.text! ) // Optional("Button")
    print( sender.titleLabel!!.text! ) // Button

} 

What is going on here?

I have seen

but the sender is not an array here, and I couldn't see the connection to those answers.

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • 3
    See [Interacting with Objective-C APIs](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html): *"NOTE: Property access on AnyObject always returns an optional value."* and the following examples. – Martin R Oct 02 '15 at 06:01
  • So the first Optional is for a property access on `AnyObject` and the second Optional is the normal `titleLable` Optional on `UIButton`. Is that correct? – Suragch Oct 02 '15 at 06:14

2 Answers2

2

This is because of AnyObject. The first ? is for "is it an object that responds to the titleLabel method?", and the second ? is for "is the title label nil?"

If you are only hooking up a button from Interface Builder, you can use

@IBAction func buttonTapped(sender: UIButton)
Grimxn
  • 22,115
  • 10
  • 72
  • 85
jtbandes
  • 115,675
  • 35
  • 233
  • 266
  • Ah, right. I'm still curious about the meaning of double optional or unwrapping, though. What is it about `AnyObject` that makes the compiler require that? – Suragch Oct 02 '15 at 05:51
  • One `?` is for "is it an object that responds to the `titleLabel` method?" and one `?` is for "is the title label nil?" – jtbandes Oct 02 '15 at 06:13
1

When you are sure that your sender is always UIButton then why are your input parameter as AnyObject. Below declaration would solve your problem:

@IBAction func buttonTapped(sender: UIButton) {
    print( sender.titleLabel!.text ) // Optional("Button")
    print( sender.titleLabel!.text ) // Optional("Button")
    print( sender.titleLabel!.text ) // Optional("Button")

    print( sender.titleLabel!.text! ) // Optional("Button")
    print( sender.titleLabel!.text! ) // Optional("Button")
    print( sender.titleLabel!.text! ) // Button
}
Abhinav
  • 37,684
  • 43
  • 191
  • 309
  • You're right. In this case the sender is always a `UIButton` so I should have marked it as such. I would still like to know, though, why the compiler is requiring the double optional/unwrapper for `AnyObject`. – Suragch Oct 02 '15 at 05:54
  • Simply because your first level of object is not certain. It could be anything including nil so you better let compiler know what it is. You could do it by `if let button = sender as? UIButton { }` syntax as well and then fetch the `UIButton` properties inside. Its always a better practice to mention the right type and let compiler be certain pre-hand on the data type rather than we writing more code in making compiler understand that we know what could come in `AnyObject` at run time. – Abhinav Oct 02 '15 at 06:05