A variadic function means a function accepts a variable number of arguments. The example we might be most familiar with in Objective-C might be the -stringWithFormat: method of NSString. We can use this method to build a string like this:

NSString *name = @"Tom";
NSDate *date = [NSDate date];
NSString *string = [NSString stringWithFormat:
                @"Hello %@. Date: %@", name, date];

The number of arguments in this function is indefinite. The first argument is the string should be formatted, followed by several (here is two) other parameters to fill in it. We will not talk more about how to write a method to receive indefinite parameters in Objective-C (this is a Swift book after all). It is not very difficult for an Objective-C developer, but you might not be able to write it correctly without referring to documentation or Google for the first time.

However, everything gets greatly simplified in Swift. Now, you just add "..." at the end of parameter type to change it into a variadic function. The code below declares a sum function by accepting input as indefinite arguments:

func sum(input: Int...) -> Int {
    //...
}

The input will be recognized and used as an [Int]. Now, let us finish the sum function above. You can use for...in to loop all number in input. But to let our code look more "Swift", we choose the reduce function:

func sum(input: Int...) -> Int {
    return input.reduce(0, combine: +)
}

print(sum(1,2,3,4,5))
// Output: 15

Variadic in Swift is much powerful than in other languages. In a traditional programming langauge, due to the limitaion of compiler or syntax, the indefinite parameter must be the final arguments in the function. That means you cannot declare any normal arguments after "...". The compiler will have no idea about where to split the argument list. However, since we could name the parameters in Swift, there is no such limitation here. The code below is also valid:

func myFunc(numbers: Int..., string: String) {
    numbers.forEach {
        for i in 0..<$0 {
            print("\(i + 1): \(string)")
        }
    }
}

myFunc(1, 2, 3, string: "hello")
// Output:
// 1: hello
// 1: hello
// 2: hello
// 1: hello
// 2: hello
// 3: hello

We should pay attention to the type of variadic. As the input is just an array of some specified type, you cannot make multiple types in the same indefinite argument. For example, the first parameter of -stringWithFormat: must be a String, while other parameters could be any type. Of course, we can use Any as the type of variadic parameters, and check if the first parameter is a string or not. However, by doing this, we will lose the compiler check for input types and suffer a runtime overhead. Thanks to external parameter names in Swift, we can use an underscore to ignore the parameter names when calling a method. With this feature, when we declare a variadic method, we can use an anonymous variadic parameter list following a type-specified (String in this example). The formatting method of NSString in Swift is using this skill:

extension NSString {
    convenience init(format: NSString, _ args: CVarArgType...)
    //...
}

When calling, the API is almost the same as the one in Objective-C:

let name = "Tom"
let date = NSDate()
let string = NSString(format: "Hello %@. Date: %@", name, date)