Merricat
Merricat

Reputation: 2841

How to pass closure with parameters to a function? (Swift)

So I have a function that I need to execute when a condition is met, and if it's not, just wait 0.2 seconds, then try again (recursively).

func myFunction(_ str1: String? = nil, _str2: String? = nil)
{
    //whatever
}

(Note that I gave the arguments a default value, so I can call this function without specifying any parameters). Now, here's my 'delay' function:

func delay(_ function: @escaping (String?, String?) -> Void)
{
    if !myExternalCondition
    {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            self.delay(function)
        }
    }
    else
    {
        function()    //error
    }
}

This gives me the following error: Missing argument for parameter #1 in call

Honestly, I'd like the delay function to take in any type of closure, regardless of its arguments (amounts or types). Any help is appreciated ;)

Edit: in case it's not clear, I want to be able to take any closure (capture it with all of its parameters) and execute it when it's ready.

Upvotes: 1

Views: 1600

Answers (1)

Rob Napier
Rob Napier

Reputation: 299345

I think you're misunderstanding how default parameters work. Default parameters are just a syntax helper. They make it easier to call the function directly in code, but they don't change the function itself. There's no way that you could support any number of parameters if they were actually required; you'd need to pass something.

So just expand this to make the syntax convenience explicit with an overload:

func myFunction(_ str1: String?, _str2: String?)
{
    //whatever
}

func myFunction() {
    myFunction(nil, nil)
}

And then you can call it.

func delay(_ function: @escaping () -> Void)
{
    if !myExternalCondition
    {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            self.delay(function)
        }
    }
    else
    {
        function()
    }
}

It's possible you've just misunderstood how closures work. With the above delay, the following is fine using your original definition of myFunction (with default parameters):

delay { myFunction() }

The following is also fine:

delay { myFunction("xyz") }

The point is that the closure has no parameters. You may be thinking of myFunction as the "closure" but that's not correct. The closure is the {...} part. If it had parameters, you'd expect a x in syntax or $0 somewhere in it.

Upvotes: 2

Related Questions