1

I'm attempting to pass in a function to add as a target to a UIButton in Swift3, but I'm getting the following error:

Argument of '#selector' does not refer to an '@objc' method, property, or initializer

Here's my code:

func updateButtonAction(_ action: () -> (), button: UIButton) {
    button.addTarget(self, action: #selector(customFunction(action)), for: .touchUpInside)
}

func customFunction(_ function: () -> ()) {
    function()
}

I'm wrapping a passed in function in another function so I know the class that owns it.

I think the issue is that first class functions in Swift aren't supported in Objective-C and the selector keyword only uses Objective-C functions.

Does anyone know a way around this?

rmooney
  • 6,123
  • 3
  • 29
  • 29
  • The duplicate question has the best solution here, although my solution was to avoid first class functions and pass in the selector from another class. – rmooney Mar 30 '17 at 14:43

1 Answers1

1

Selector is just a fancy synonym for method name. It's not a closure or a function. It's the name of a method on an Obj-C object. Technically, a selector is a string.

customFunction(action) is not a selector. The selector is customFunction(_:).

You are trying to pass an implicit parameter to the selector. That's not how selectors work. You are not calling the method, you are just telling the UIButton which method it should call - UIButton is calling the method and the button is also specifying the parameters.

If you need to pass some code to the event handler, save it on your instance.

var function: (() -> Void)?

func customFunction() {
    self.function?()
}

In general it's a good idea to have only one event handler and not change it.

Also note that your example has no need for first class functions.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Thanks for your answer. My goal was to avoid saving it on the instance. I was able to solve my problem by passing in the parent object and the selector already created in another class instead of just the function wrapped locally. – rmooney Mar 30 '17 at 14:42
  • @rmooney I understand what you were trying to do but unfortunately this is a very old API which existed before Obj-C had closures. You can easily subclass `UIButton` and add a method that will take a closure instead (the button can hold it) but in 90% cases the event handlers are connected from storyboards/xibs, therefore most people don't bother with subclasses. – Sulthan Mar 30 '17 at 14:46
  • That's a good option as well, but I ended up not needing it. – rmooney Mar 30 '17 at 15:48