1. 函数
1.1 函数的定义
func pi() -> Double{
return 3.14
}
func sum(v1:Int,v2:Int) -> Int{
return v1+v2
}
sum(v1: 10, v2: 20)
func sayHello() -> Void{
print("Hello")
}
func sayHello2() -> (){
print("Hello")
}
func sayHello3(){
print("Hello")
}
1.2 隐式返回
- 如果整个函数是一个单一的表达式,那么函数会隐式返回这个表达式
func sum2(v1:Int,v2:Int) -> Int{
v1+v2
}
sum(v1: 10, v2: 20)
1.3 返回元组
func calculate(v1:Int,v2:Int) -> (sum:Int,difference:Int,average:Int){
let sum = v1 + v2
return (sum,v1 - v2,sum >> 1)
}
let result = calculate(v1: 20, v2: 10)
result.sum
result.difference
result.average
1.4 函数的文档注释
func sum3(v1:Int,v2:Int) -> Int{
v1+v2
}

1.5 参数标签
func goToWork(at time:String){
print("this time is \(time)")
}
goToWork(at: "08:00")
func sum(_ v1:Int,_ v2:Int) -> Int{
v1 + v2
}
sum(10,20)
1.6 默认参数值
func check(name:String = "nobody",age:Int,job:String = "none"){
print("name=\(name),age=\(age),job=\(job)")
}
check(name: "Jack", age: 20, job: "Doctor")
check(name: "Rose", age: 18)
check(age: 10, job: "Batman")
check(age: 15)
- C++的默认参数必须从右往左设置。C++的默认参数必须从右往左设置。由于swift拥有参数标签,并没有此类限制。但是在省略参数标签时,需要特别注意出错。
func test(_ first:Int = 10,middle:Int = 20,_ last:Int = 30){}
test(middle:20)
1.7 可变参数
func sum4(_ numbers:Int...) -> Int{
var total = 0
for number in numbers {
total += number
}
return total
}
sum4(10,20,30,40)
- 一个函数最多只能有一个可变参数,紧跟在可变参数后面的参数不能省略参数标签
func test(_ numbers:Int...,string:String,_ other: String){}
test(10,20,30,string:"Jack","Rose")
print(1,2,3,4,5)
print(1,2,3,4,5,separator:"_")
1.8 输入输出参数
- 可以用inout定义一个输入输出参数:可以在函数内部修改外部实惨的值
func swapValues(_ v1: inout Int,_ v2:inout Int){
let tmp = v1
v1 = v2
v2 = tmp
}
var num1 = 10
var num2 = 20
swapValues(&num1, &num2)
func swapValues2(_ v1: inout Int,_ v2:inout Int){
(v1,v2) = (v2,v1)
}
- 可变参数不能标记为inout。inout参数不能有默认值。inout参数只能传入可以被多次赋值的(var)。inout参数的本质是地址传递(引用传递)。
1.9 函数重载
- 函数名相同,函数参数不同||参数类型不同||参数标签不同
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
func sum(v1:Int,v2:Int,v3:Int) -> Int{
v1+v2+v3
}
func sum(v1:Int,v2:Double) -> Double{
Double(v1)+v2
}
func sum(v1:Double,v2:Int) -> Double{
v1+Double(v2)
}
func sum(_ v1:Int,_ v2:Int) -> Int{
v1+v2
}
func sum(a:Int,b:Int) -> Int{
a+b
}
- 注意:返回值类型和函数重载无关

- 注意:默认参数值和函数重载一起使用产生二义性时,编译器并不会报错(c++中会报错)
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
func sum(v1:Int,v2:Int,v3:Int = 10) -> Int{
v1+v2+v3
}
sum(v1: 10, v2: 20)//会调用sum(v1:Int,v2:Int)
- 注意:可变参数/省略参数标签,函数重载一起使用产生二义性时,编译器可能会报错
1.10 内联函数
- 如果开启了编译器优化(Release模式会默认开启优化),编译器会自动将某些函数变为内联函数,将函数的调用展开成函数体
- 不会被自动内联的情况:函数体比较长,包含递归调用,包含动态派发
- inLine
@inline(never) func test1(){print("test")}
@inline(__always) func test2(){print("test")}
- 在Release模式下,编译器已经开始优化,会自决定哪些函数需要被内联,因此没必要使用@inline
1.11 函数类型
- 每一个函数都是有类型的,函数类型由形式参数类型,返回值类型组成
func test3(){}
func sum(x:Int,y:Int)->Int{x+y}
var fn:(Int,Int)->Int = sum
fn(2,3)
func sum(v1:Int,v2:Int) -> Int{ v1+v2 }
func difference(v1:Int,v2:Int) -> Int{ v1-v2 }
func printResult(_ mathFunc:(Int,Int)->Int,_ a:Int,_ b:Int){
print("Result:\(mathFunc(a,b))")
}
printResult(sum, 5, 2)
printResult(difference(v1:v2:), 5, 2)
- 函数类型作为函数返回值。返回值是函数类型的函数,叫做高阶函数
func next(_ input:Int)->Int{
input + 1
}
func previous(_ input:Int)->Int{
input - 1
}
func forward(_ forward:Bool)->(Int)->Int{
forward ? next(_ :) : previous(_:)
}
forward(true)(3)
forward(false)(3)
1.11 别名typealias
typealias Byte = Int8
typealias Short = Int16
typealias Long = Int64
typealias Date = (year:Int,month:Int,day:Int)
func test(_ date:Date){
print(date.0)
print(date.year)
}
test((2011,9,10))
typealias IntFn = (Int,Int) -> Int
func difference(v1:Int,v2:Int) -> Int{
v1 - v2
}
let fn:IntFn = difference(v1:v2:)
fn(20,10)
func setFn(_ fn:IntFn){}
setFn(difference(v1:v2:))
func getFn() -> IntFn{difference(v1:v2:)}
- 源码可以看出,按照swift标准库的定义, Void就是空元组
public typealias Void = ()
1.12 嵌套函数
func forward(_ forward:Bool)-> (Int) -> Int{
func next(_ input:Int) -> Int{
input + 1
}
func previous(_ input:Int) -> Int{
input - 1
}
return forward ? next : previous(_:)
}
forward(true)(3)
forward(false)(3)