web-dev-qa-db-ja.com

Swiftの関数の配列

JavaScriptのように、後でコールバックする関数の配列を配列に保存するにはどうすればよいですか? AnyおよびAnyObjectタイプは、異なるタイプのメソッドシグネチャを持つ関数を保持できません。

21
Encore PTL

Enumを使用してさまざまな関数を配列に入れ、スイッチで関数を抽出できます。

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

注:この回答はSwiftバージョン1.0以下用です。

パラメータと戻り値の型が異なる関数は型が異なるため、一緒に配列に格納することはできません。また、AnyまたはAnyObjectプロトコルにも準拠していません。

同じパラメータを持つ関数がある場合は、それを回避できます。以下の関数はDoubleとIntのタプルを返しますが、どちらも() -> Any関数型として定義できます。

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]
8
Connor

以下は、配列と辞書の両方の例です。 Xcode 6.1(6A1046a)でテストおよび動作。辞書の関数は最初にアンラップする必要があることに注意してください。

ただし、この手法は、connorが彼の回答で説明した理由により、関数のパラメーターまたは戻り値の型が異なる場合、バラバラになります。

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

Swift 1.1以降、すべての関数型はAnyに準拠しているため、Any配列に関数を保持できます。

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]
3
Connor