Lance Pollard
Lance Pollard

Reputation: 79248

How to pass functions from class instance into array in Swift

Not sure if this is the best approach but I want to have functions accessible by an index and would prefer not to use a dictionary. So I was thinking of putting them into an array.

var array = [ func1, func2, ... ]

It looks like this is possible since functions are first class citizens.

BUt I'm wondering if you can do this on classes. That is, pass a function from a class instance to an array, without losing performance with extra closures.

class Foo {
  var array: [Function]

  init() {
    array = [ f1, f2 ]
  }

  func f1() {
    return array.length
  }

  func f2(a: Int, b: Int) {
    // ... the functions are all different.
  }
}

Wondering if anything like that is possible.

Upvotes: 0

Views: 503

Answers (1)

Josh Homann
Josh Homann

Reputation: 16327

Swift Arrays are homogeneous, but you can use Any to box any type at the expense of losing the type information, so yes you can stick all of your functions into a single array even though they have different types. I don't particularly think its a good idea, but it does in fact work:

import UIKit
import PlaygroundSupport


class Foo {
    var array: [Any] = []

    init() {
        array = [ f1, f2 ]
    }

    func f1() -> Int {
        return array.count
    }

    func f2(a: Int, b: Int) {
        // ... the functions are all different.
    }
}

maybe this is slightly less horrible if you use the Objective C run time, since its dynamic and you can use actually use perform selector with arguments to invoke the selectors, but I still don't recommend it:

import UIKit
import PlaygroundSupport


class Foo {
    var array: [Selector] = []

    init() {
        array = [#selector(f1), #selector(f2) ]
    }

    @objc func f1() -> Int {
        return array.count
    }

    @objc func f2(a: Int, b: Int) {
        // ... the functions are all different.
    }
}

EDIT:

Option 3, enum with associated values (come up with more meaningful names than I have here):

import UIKit
import PlaygroundSupport


class Foo {

    enum Function {
        case void_Int(() -> Int)
        case intInt_Void((Int,Int) -> Void)
    }

    var array: [Function] = []

    init() {
        array = [.void_Int(f1), .intInt_Void(f2) ]
    }

    @objc func f1() -> Int {
        return array.count
    }

    @objc func f2(a: Int, b: Int) {
        // ... the functions are all different.
    }
}

Upvotes: 2

Related Questions