Encore PTL
Encore PTL

Reputation: 8214

Array of functions in Swift

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.

Upvotes: 28

Views: 20823

Answers (5)

Riyad Arshad
Riyad Arshad

Reputation: 26

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
}

Upvotes: 0

Connor
Connor

Reputation: 64644

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]

Upvotes: 3

Connor
Connor

Reputation: 64644

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]

Upvotes: 8

dvs
dvs

Reputation: 12422

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)()
    }
}

Upvotes: 7

Bruce1q
Bruce1q

Reputation: 522

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
        }
    }

Upvotes: 29

Related Questions