将数组传递给Swift中具有可变数量的args的函数

时间:2014-06-03 20:29:18

标签: swift variadic-functions

The Swift Programming Language中,它说:

  

函数也可以使用可变数量的参数,将它们收集到一个数组中。

  func sumOf(numbers: Int...) -> Int {
      ...
  }

当我用逗号分隔的数字列表(`sumOf(1,2,3,4))调用这样的函数时,它们在函数内作为数组提供。

问题:如果我已经有一个数字数组要传递给这个函数怎么办?

let numbers = [1, 2, 3, 4]
sumOf(numbers)

这会因编译错误而失败,“无法找到' __转换过载'接受提供的参数“。有没有办法将现有数组转换为可以传递给可变函数的元素列表?

8 个答案:

答案 0 :(得分:86)

开发人员证实,

Splatting is not in the language yet。现在的解决方法是使用重载或等待,如果你不能添加重载。

答案 1 :(得分:59)

这是我发现的一项工作。我知道这不是你想要的,但似乎有效。

步骤1:使用数组而不是可变参数声明您想要的函数:

func sumOf(numbers: [Int]) -> Int {
    var total = 0
    for i in numbers {
        total += i
    }
    return total
}

第2步:在你的可变函数中调用它:

func sumOf(numbers: Int...) -> Int {
    return sumOf(numbers)
}

第3步:以任何一种方式打电话:

var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])

这看起来很奇怪,但它在我的测试中起作用。如果这会导致任何人无法预料的问题,请告诉我。 Swift似乎能够用相同的函数名分隔两个调用之间的区别。

此外,使用此方法,如果Apple更新语言@ manojid的答案建议,您只需要更新这些功能。否则,您将不得不经历并进行大量重命名。

答案 2 :(得分:13)

你可以施放这个功能:

typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])

答案 3 :(得分:12)

您可以使用辅助函数:

func sumOf (numbers : [Int])  -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumArray (numbers) }

答案 4 :(得分:1)

我知道这个回答并没有回答你的确切问题,但我觉得值得注意。我也开始玩Swift并立即遇到类似的问题。 Manojlds的回答对你的问题更好,我同意,但同样,我提出了另一种解决方法。我碰巧也喜欢洛根更好。

在我的情况下,我只是想传递一个数组:

func sumOf(numbers: Array<Int>) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}

var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])

只是想分享,以防其他人像我一样思考。大多数时候我更喜欢像这样传递数组,但我不认为&#34; Swiftly&#34;然而。 :)

答案 5 :(得分:1)

我做了这个(Wrapper + Identity Mapping):

func addBarButtonItems(types: REWEBarButtonItemType...) {
    addBarButtonItems(types: types.map { $0 })
}

func addBarButtonItems(types: [REWEBarButtonItemType]) {
    // actual implementation
}

答案 6 :(得分:0)

正如我在一分钟前开始包装os_log时所了解到的那样,现在这似乎是隐含的:

func logDefault(_ message: StaticString, _ args: CVarArg...) {
    os_log(message, log: OSLog.default, type: .default, args)
}

我正在使用Xocde 11,Swift 5.1,iOS 13。

奇怪的是,当我尝试将代码放入Swift包中时,即使将iOS 13设置为唯一平台,我仍然会遇到此错误:

Argument type '[CVarArg]' does not conform to expected type 'CVarArg'

答案 7 :(得分:0)

快捷键5

这是一种具有@dynamicCallable功能的方法,该功能可以避免过载或unsafeBitCast,但是您应该拨打特定的struct来调用:

@dynamicCallable
struct SumOf {
    func dynamicallyCall(withArguments args: [Int]) -> Int {
        return args.reduce(0, +)
    }
}

let sum = SumOf()

// Use a dynamic method call.
sum(1, 2, 3) // 6

// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6