一. swift函数允许用元组作为返回值,以达到函数返回多个值的目的。
// 用元祖作为函数返回值
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
注意点:
- minMax函数返回了一个包含两个 Int 值的元组。但是函数不会对传入数组执行任何安全检查,如果 array 参数是一个空数组,那么minMax在试图访问 array[0] 时会触发一个运行时错误(runtime error)。为了安全地处理这个“空数组”问题,将 minMax(_:) 函数改写为使用可选元组返回类型,并且当数组为空时返回 nil;写法如下:
func minMax(array: [Int]) -> (min: Int, max: Int?) { ... }
- 由于元组的成员值已被命名,所以可以通过点语法来检索到最小值或最大值,并且元祖的成员不需要在元祖从函数中返回时命名,因为它们的名字已经在函数返回类型中指定了。
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
二. 函数的参数
每个函数的参数都有一个参数标签(Argument Label)以及参数名称(Parateter Name)。不指定的情况下,参数名称就是函数参数的参数标签。
参数名称在函数实现中使用;
参数标签在函数调用时使用;
参数标签写在参数名称前面,以空格分开。
一个函数中多个参数的参数名称唯一,参数标签可重复,但不推荐。
1. 参数标签使用:让函数类似自然语言,提高了可读性。
func foo(person name: String, from hometown: String) {
print(name)
}
foo(person: "lzf", from: "china")
2. 忽略参数标签:如果想隐藏(忽略)参数标签,用下划线_代替。
func someFunc(_ age: Int, height: Double) {}
someFunc(20, height: 178)
3. 默认参数值:通过给参数赋值定义默认参数值,函数调用时可忽略此参数。
也可以对此参数重新赋值,调用函数时会出现两个函数提示!
一般将带有默认值的参数放在最后,函数调用时语意更清晰。如下:
func someFunc(height: Double, age: Int = 20) {}
someFunc(height: 178)
// 或者
someFunc(height: 180, age: 18)
4. 可变参数:一个可变参数可以接收零个或多个值。
通过在变量类型名后加...来定义可变参数,
可变参数的传入值在函数体中变为此类型的数组。
注意:一个函数中只能有一个可变参数。
// 计算一组任意长度数字的算术平均值
func average(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
average(1, 2, 37, 48, 19, 199)
输入输出参数:函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误(compile-time error)。这意味着你不能错误地更改参数值。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)。
定义一个输入输出参数时,在参数定义前加 inout 关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看输入输出参数一节。
你只能传递变量给输入输出参数。你不能传入常量或者字面量(literal value),因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加 & 符,表示这个值可以被函数修改。
注意:输入输出参数不能有默认值,而且可变参数不能用 inout 标记!!!
5. 输入输出参数:在变量名前面加 inout 关键字
// 定义函数交换两个整型变量的值
func swapInts(_ a: inout Int, _ b: inout Int) {
let tempA = a
a = b
b = tempA
}
var intA = 3
var intB = 120
swapInts(&intA, &intB)
print("intA = \(intA)\nintB = \(intB) ")
上面的例子中,intA和intB的原始值在函数中被修改了,尽管他们定义在函数体外。注意:输入输出参数和函数返回值时不一样的。上面的函数并没有定义返回值。所以,输入输出参数是函数对函数体外的变量产生影响的方式之一。
三. 函数的类型
在swift中,使用函数类型就像使用其他类型一样。你可以定义一个类型为函数的常量或变量,并将相同类型的函数赋值给它:
func add(_ a: Int, _ b: Int) -> Int { // 加法
return a + b
}
func multiply(_ a: Int, _ b: Int) -> Int { // 乘法
return a + b
}
// 1.将add函数赋值给函数变量mathFunc
var mathFunc: (Int, Int) -> Int = add
// 2.然后用mathFunc调用add函数
mathFunc(10, 20)
// 3.也可以将multiply函数赋值给mathFunc,因为它们函数类型一样
mathFunc = multiply
mathFunc(10, 20)
// 4.和其他类型一样,将函数赋值给一个常量或变量时,swift会自动推导类型:
let anotherMathFunc = add // 被推导为(Int, Int) -> Int类型函数