Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 775
moyoteg Avatar asked Sep 22 '16 18:09

moyoteg


2 Answers

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.]

like image 170
robotpie Avatar answered Jan 05 '23 06:01

robotpie


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...

like image 33
Sinisa Vukovic Avatar answered Jan 05 '23 07:01

Sinisa Vukovic