Search code examples
xcode8ibaction

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?


Solution

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