There are multiple functions in my app, where each have a different number of parameters
func functionOne(foo: Foo, bar: Bar)
func functionTwo(foo: Foo, bar: Bar, baz: Baz, quux: Quux)
func functionThree(foo: Foo)
The parameter values can vary.
My requirement is to press a button which will run whichever function of the above was run most recently, including its parameter values.
Storing the whole thing (function and parameters) in a variable did not work.
A function and its parameters are stored in a closure. For example:
func f(_ x: Int) {}
func g(_ x: Int, _ y: Int) {}
var saved: () -> Void = { f(1) }
saved() // this executes f(1)
saved = { g(2, 3) }
saved() // now this executes g(2, 3)
You can use @escaping
and @autoclosure
to store a function and its parameters as a closure in a property of your class
and then call it.
Add this class to your project:
// Stored Function Class
class SFC {
static var calledFunc: (() -> Void)?
static func call(_ function: @escaping @autoclosure () -> Void) {
// Store the function
calledFunc = function
// Call it
function()
}
static func reCall() {
// Called the stored function
calledFunc?()
}
// Call this when you no longer want SFC to hold onto your function.
// Your class will not deallocate if you passed in `self` to `call()`
// as long as `calledFunc` retains your function. Setting it to `nil`
// frees it.
static func forget() {
calledFunc = nil
}
}
This is how you use it:
Wrap any function call that you want to repeat with SFC.call()
. Call SFC.reCall()
to call that function again.
Example:
func add(_ a: Int, _ b: Int) {
print("\(a) + \(b) = \(a + b)")
}
SFC.call(print("hello", "bye"))
SFC.reCall()
SFC.reCall()
SFC.call(add(2, 3))
SFC.reCall()
Output:
hello bye hello bye hello bye 2 + 3 = 5 2 + 3 = 5
How does this work?
The contents of the call to call()
are automatically wrapped in a closure (that is what @autoclosure
does) and passed as function
. The @escaping
means that you'll be hanging onto that closure after call()
returns.
That closure is then assigned to the calledFunc
property so that it can be called again later from reCall()
.
Note: If the function you are passing to call()
is a member function, you'll need to explicitly specify self
. For example: SFC.call(self.functionThree(foo: fooVar))
. Be sure to call SFC.forget()
when it's time for your class to be freed so that SFC
doesn't hold onto your class instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With