How can I store an array of functions to callback later in an array like in JavaScript? Any and AnyObject type cannot hold functions with different types of method signatures.
-
Without exception handling, I can't think of any use for this. Could you add a little more context to the question for us? – Jiaaro Jun 25 '14 at 21:39
-
Take a look at closures, they're pretty much ideal for things like that. – David Berry Jun 25 '14 at 21:48
-
1`Array
Void>` or unreadable version `(()->())[]` – Bryan Chen Jun 25 '14 at 22:18 -
My use case is to keep an array of function that I keep passing the result of one function to another. Some of them may take two parameters some may take only one. – Encore PTL Jun 27 '14 at 02:03
-
As of Swift 1.1, `Any` can hold functions. – newacct Oct 17 '14 at 19:43
-
@Jiaaro I came up with the idea of creating an array of buttons with a loop, programmatically. Since I want each button to act slightly different when touched (thus no structure), I think an array of functions to react to each button by reference number would be a reason to use an array of functions. Thoughts... – Scuttle Mar 12 '19 at 02:56
5 Answers
You can use an enum to put various functions into the Array and then extract the functions with a switch.
enum MyFuncs {
case Arity0 ( Void -> Void )
case Arity2 ( (Int, String) -> Void)
}
func someFunc(n:Int, S:String) { }
func boringFunc() {}
var funcs = Array<MyFuncs>()
funcs.append(MyFuncs.Arity0(boringFunc))
funcs.append( MyFuncs.Arity2(someFunc))
for f in funcs {
switch f {
case let .Arity0(f):
f() // call the function with no arguments
case let .Arity2(f):
f(2,"fred") // call the function with two args
}
}

- 504
- 4
- 8
-
1I logged in just to upvote this answer. This idea looks awesome, provided that you can at compile time write all the possible combinations of function types on the enum. – Alex Jul 04 '14 at 15:36
-
Odd, it works for me in a playground at global scope, but not if I use inside a class. – netskink Feb 20 '16 at 20:21
-
Ahh, it does work. I need to move some of the lines to a routine. Never mind. Many thanks for the neat code. – netskink Feb 20 '16 at 21:21
-
Note: this answer is for Swift versions 1.0 and lower.
Functions that have different parameters and return types are of a different type so they can't be stored in an array together. They also don't conform to the Any or AnyObject protocols.
If you have functions with the same parameters though you can work around that. Even though the functions below return a tuple of Double and an Int, they can both be defined as () -> Any
function types.
func func1 () -> Int {
return 1
}
func func2 () -> (Double, Double){
return (2, 3)
}
var a: () -> Int = func1
var b: () -> (Double, Double) = func2
var arr: Array< () -> Any> = [a, b]

- 63,902
- 28
- 145
- 142
-
Lets say I want to take one function with two parameters as input and one with only one parameter. This doesn't work then. – Encore PTL Jun 27 '14 at 02:04
-
Yeah. There is no solution. This is just a workaround that works in a specific case – Connor Pearson Jun 27 '14 at 02:06
-
@EncorePTL, the scenario you are highlighted just won't work in practice, even if you'd be keen to store method with various parameter list, that is practically a useless array of methods. – holex Jun 27 '14 at 09:23
-
I can always invoke functions as such `function(reinterpretCast(args))` where args is an array which gets converted to appropriate parameters in the function – Encore PTL Jun 27 '14 at 19:09
-
I want to store functions so I can lazily evaluate the values in the end. – Encore PTL Jun 27 '14 at 19:10
Below is an example with both an array and a dictionary. Tested and working in Xcode 6.1 (6A1046a). Note that functions from dictionaries must first be unwrapped.
This technique does however fall apart when the functions have different parameter or return types, for the reasons explained by connor in his answer.
class MyViewController: UIViewController
{
let arrayOfFunctions = [function1, function2]
let dictionaryOfFunctions = [
"function1": function1,
"function2": function2
]
func function1() {
NSLog("function1")
}
func function2() {
NSLog("function2")
}
override func viewDidLoad()
{
let fn1 = arrayOfFunctions[0]
fn1(self)()
let fn2 = dictionaryOfFunctions["function2"]
fn2!(self)()
}
}

- 12,324
- 6
- 38
- 45
-
works on xcode 9.2 and swift 3.2. Used it like `var actions = [add, massText] if condition { actions.insert(massMsg, at: 1) }` call by `actions[selectedIndex]()` – anoo_radha Feb 07 '18 at 16:50
As of Swift 1.1, all function types conform to Any, so you can hold functions in an Any array.
func foo (str: String) -> Int {
return 1
}
func bar () -> (Double, Double){
return (2, 3)
}
var a: Any = foo
var b: Any = bar
var arr: Any = [a, b]

- 63,902
- 28
- 145
- 142
A simpler approach to call stored function in array on demand , to use parameters a simple workaround is to make dict args
and use it inside the function.
var args = [ "a" : 1, "b" : 2 ]
var requestQueue : [() -> Void] = []
func a() -> Void {
let param = args["a"]
print(param!)
}
func b() -> Void {
let param = args["b"]
print(param!)
}
requestQueue.append(a)
requestQueue.append(b)
for item in requestQueue {
item() //calling the functions
}

- 26
- 3