Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't default parameters for functions respected when called via Selector in Swift?

Methods called via Selector don't respect default parameter values.

EXAMPLE

If I have a button wired up to call a function via a selector:

func setupButton() {
    self.button.addTarget(self, action: #selector(printValue), for: .touchUpInside)
}

@objc func printValue(value:Int = 7)
{
    if value == 7 {
       print("received default")
    } else {
       print("default unused")
    }
}

When calling this method via code "received default" is printed, but when I press the button and call the method via selector "default unused" is printed because 7 wasn't set as the value.


Why is this happening?

like image 610
Dan Carlson Avatar asked Jan 25 '23 22:01

Dan Carlson


1 Answers

Default parameters are inserted by the Swift compiler when you call the function.
So this is a compile-time thing.

When manually calling the function via a selector, you use the Objective-C runtime, which has no idea about your default parameters.
This is a runtime thing.

Moreover, default parameters don't exist in Objective-C.

You can think of Swift default parameters as a compile-time convenience.
But once you run your code, they're basically gone.

EDIT

If you're looking for a workaround, I can suggest having two different functions, without using default parameters:

@objc func printValue()
{
    printValue(value: 7)
}

@objc func printValue(value:Int)
{}

This way, you can call it without arguments through the Objective-C runtime. Note that when using #selector, you'll need to cast to resolve ambiguity:

self.button?.addTarget(self, action: #selector((printValue as () -> Void)), for: .touchUpInside)
like image 64
Macmade Avatar answered May 16 '23 06:05

Macmade