15

Xcode 8 drag and connect @IBAction incorrectly adds "WithSender" on connection inspector IB

Therefore I have to rename the methods to something like

@IBAction func tappedConfirmButtonWithSender(sender: AnyObject) {}

Shouldn't it be?:

@IBAction func tappedConfirmButton(sender: AnyObject) {}

Is this my fault or is this a bug?

moyoteg
  • 351
  • 3
  • 11

4 Answers4

31

I've just hit this as well. It appears to be a bug with legacy Swift 2.3 code, due to a bit of Swift 3 leaking in. I found the key answers in the dev forums, plus some additional findings by me and my coworker.

Workaround: Change the argument (sender: AnyObject) to (_ sender: AnyObject). You'll get a warning on the modified line that you can safely ignore.

[UPDATED - another workaround: Apple responded to my bug report and suggested a different workaround: annotate the @IBAction method with @objc. I haven't yet confirmed that that works.]

What's going on: It looks like there's a bug in Xcode 8 storyboards. My interpretation is that it's mistakenly parsing Swift 2 @IBAction methods as if they were Swift 3, and then attempting to convert them back to Swift 2.

Let's get detailed! In Swift 3, unlike Swift 2, given a method declared as:

@IBAction func foo(sender: AnyObject)

the sender argument label is actually part of the method name and gets included in calls to that method. In Swift 2, of course, the first argument does not get a label by default. In Swift 2, you'd call foo(myButton); in Swift 3, you'd call foo(sender: myButton).

Xcode 8 is mistakenly reading this function the Swift 3 way. And the pattern for the Grand Renaming of the APIs is that Swift 2 method names of the form doSomethingWithParam(quuz) are rewritten for Swift 3 as doSomething(param: quuz). Xcode assumes that's what happened here, so in a misguided attempt to derive the original Swift 2 name, it adds WithSender back to the end of the method name. The underscore workaround works by making the Swift 3 method signature identical to the Swift 2 one. (I don't know why the @objc annotation also solves the problem, according to Apple.)

[Edited repeatedly with changes to workarounds.]

robotpie
  • 426
  • 4
  • 4
  • 4
    Thanks for the detailed update! I figured something like that was happening. My current **workaround** is to **connect the @IBAction and then look at the actual outlet (right click on the view element) on Interface Builder** which shows the string literal for the selector on the **black pop up** and so I just have to **update the function name to match that.** – moyoteg Sep 24 '16 at 20:01
  • Thanks for solving this problem. I can't believe the amount of bugs and issues that have come with Xcode 8 and Swift 3. I had a working project prior to the upgrade. I've spent no less than 8 hours fixing things to make the project work after the updates. Everything from missing header files to broken pod dependencies to IB Auto layout issues and now event handlers. SMH – itsben Oct 01 '16 at 22:00
  • 1
    Thanks for the work arounds and explanation, the apple suggested one 'adding @objc annotation' doesn't work for me. so i guess we should stick with the '_ ' for now. – Xu Yin Oct 07 '16 at 21:04
1

I have finally found topic with the problem I am having. I have started to doubt myself.

I will propose one more workaround for those who are interested.

Open your storyboard with right click -> Open as -> Source Code.

Find your method in xml file and delete WithSender addition to match your method name with the one in your class.

This way you can have your method name the way you want.

Thats it...

0

I had the same issue while working with Xcode 8. It may be bug.

Screenshot 1

Below is work around for this issue :

  1. Delete the outlet connection from IB file

  2. Create a new outlet by Ctrl and drag. This opens a pop-up as shown below.

Screenshot 2

Select Connection as Action and enter name of action. Then select Type.

  1. Press Connect. This will create new IBAction in your Swift file. Although the circle for IBAction may not be filled but it is connected.

Screenshot 4

Jayprakash Dubey
  • 35,723
  • 18
  • 170
  • 177
0

You can try to change it as following:

@IBAction func tappedConfirmButton(_ sender: AnyObject) 
{

}

Good luck!

Lin
  • 497
  • 5
  • 15