【问题标题】:Array of functions in SwiftSwift 中的函数数组
【发布时间】:2014-08-16 14:57:38
【问题描述】:

我怎样才能像在 JavaScript 中那样将函数数组存储到稍后回调的数组中? Any 和 AnyObject 类型不能保存具有不同类型方法签名的函数。

【问题讨论】:

  • 没有异常处理,我想不出有什么用。您能为我们的问题添加更多背景信息吗?
  • 看看闭包,它们非常适合这样的事情。
  • Array<Void -> Void> 或不可读版本(()->())[]
  • 我的用例是保留一个函数数组,我不断将一个函数的结果传递给另一个函数。其中一些可能需要两个参数,一些可能只需要一个。
  • 从 Swift 1.1 开始,Any 可以保存函数。

标签: swift swift-playground


【解决方案1】:

注意:此答案适用于 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]

【讨论】:

  • 假设我想将一个带有两个参数的函数作为输入,一个只有一个参数。那就不行了。
  • 是的。没有解决办法。这只是在特定情况下有效的解决方法
  • @EncorePTL,你强调的场景在实践中是行不通的,即使你热衷于存储带有各种参数列表的方法,这实际上是一个无用的方法数组。跨度>
  • 我总是可以像 function(reinterpretCast(args)) 这样调用函数,其中 args 是一个数组,它被转换为函数中的适当参数
  • 我想存储函数,这样我就可以懒惰地评估最后的值。
【解决方案2】:

您可以使用枚举将各种函数放入数组中,然后通过开关提取函数。

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

【讨论】:

  • 我登录只是为了支持这个答案。这个想法看起来很棒,前提是您可以在编译时在枚举上编写所有可能的函数类型组合。
  • 奇怪,它在全局范围内的操场上对我有用,但如果我在类中使用则不行。
  • 啊,它确实有效。我需要将一些行移到例程中。没关系。非常感谢简洁的代码。
  • 如果boringFunc可以抛出怎么办?那就不行了
【解决方案3】:

下面是一个包含数组和字典的示例。在 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)()
    }
}

【讨论】:

  • 适用于 xcode 9.2 和 swift 3.2。像var actions = [add, massText] if condition { actions.insert(massMsg, at: 1) }actions[selectedIndex]()调用一样使用它
【解决方案4】:

从 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]

【讨论】:

  • 那你怎么称呼他们呢?
【解决方案5】:

按需调用数组中存储的函数的更简单方法,使用参数一个简单的解决方法是制作 dict args 并在函数内部使用它。

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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    相关资源
    最近更新 更多