Hay múltiples funciones en mi aplicación, donde cada una tiene una cantidad diferente de parámetros
func functionOne(foo: Foo, bar: Bar) func functionTwo(foo: Foo, bar: Bar, baz: Baz, quux: Quux) func functionThree(foo: Foo)Los valores de los parámetros pueden variar.
Mi requisito es presionar un botón que ejecutará cualquier función de las anteriores que se haya ejecutado más recientemente, incluidos los valores de sus parámetros.
Almacenar todo (función y parámetros) en una variable no funcionó.
Una función y sus parámetros se almacenan en un cierre. Por ejemplo:
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)Puede usar @escaping y @autoclosure para almacenar una función y sus parámetros como cierre en una propiedad de su class y luego llamarla.
Agregue esta clase a su proyecto:
// 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 } }Así es como lo usas:
Envuelva cualquier llamada de función que desee repetir con SFC.call() . Llame a SFC.reCall() para volver a llamar a esa función.
Ejemplo:
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()Producción:
hello bye hello bye hello bye 2 + 3 = 5 2 + 3 = 5
¿Como funciona esto?
El contenido de la llamada a call() se envuelve automáticamente en un cierre (eso es lo que hace @autoclosure ) y se pasa como function . El @escaping significa que te aferrarás a ese cierre después de que call() regrese.
Luego, ese cierre se asigna a la propiedad calledFunc para que se pueda volver a llamar más tarde desde reCall() .
Nota: si la función que está pasando a call() es una función miembro, deberá especificar explícitamente self . Por ejemplo: SFC.call(self.functionThree(foo: fooVar)) . Asegúrese de llamar a SFC.forget() cuando sea el momento de liberar su clase para que SFC no retenga su instancia de clase.