Functions and Closures
github:Swift基础实例
github:SwiftBasicTableView
函数
- 函数声明
用func
声明一个函数,通过函数名来调用函数,函数如果有参数,在圆括号()
中需要跟上相应参数。用符号->
把函数的参数和函数的返回值类型隔开。
var nameAndDay = ""
func greet(name: String, day: String, number: Int) ->String {
return "Hello \(name), today is \(day), \(number)."
}
nameAndDay = greet("Swift", day: "Sunday", number: 1)
print(nameAndDay)
- 输出
Hello Swift, today is Sunday, 1.
- 函数返回多个值
从函数返回多个值时,可以使用元组tuple
,通过 名字 或 索引来访问tuple
中的值:
func calculate(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
}
else if score < min {
min = score
}
sum += score
}
return (min,max,sum)
}
let statistics = calculate([5, 10, 39, 5])
print(statistics.sum)
print(statistics.1)
- 参数数量可变的函数
func sumOf(numbers:Int...) ->Int {
var sum = 0
// numbers.count
for number in numbers {
sum += number
}
return sum
}
print(sumOf())
print(sumOf(1,3,4,5))
- 上面代码中,一系列的参数放在了一个数组
numbers
中
- 函数嵌套
嵌套函数中,内层函数可以使用外层函数中的变量。一个函数中的代码如果太长,或者比较复杂,那么可以使用嵌套函数来组织组织这些代码:
func returnFifteen() ->Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
print(returnFifteen())
- 返回函数
Swift
的函数是第一类类型first-class type
,这意味着一个函数可以把其他函数作为它的返回值:
func makeIncrementer() ->((Int)->Int) {
func addOne(number:Int) ->Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
print(increment(7))
- 在函数
makeIncrementer
中,构造了另外一个函数addOne
并将其返回,返回函数名就可以(猜测,可能返回的是函数指针)
- 函数作为参数
一个函数可以作为另外一个函数的参数,传递进去:
func lessThanTen(number:Int) ->Bool {
return number < 10
}
func hasAnyMatches(list:[Int], condition:(Int) ->Bool) ->Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
var numbers = [20,13,4,9]
hasAnyMatches(numbers, condition: lessThanTen)
- 传递函数时,也是只传递名称就可以
闭包(block)
闭包格式
{ (参数) -> 返回值类型 in
statements
}```
- 有名称的闭包
函数是特殊的闭包:代码块可以稍后被调用。上面的嵌套函数,就属于是有名字的闭包,无名的闭包(`匿名闭包`)是不写名字(比如`函数名`),然后把代码放在大括号`{}`中。再看下面的栗子:假设我们要写两个函数,一个计算两个数的平方的平均值,一个计算两个数的立方的平均值,一般做法是:
func square(a:Float) ->Float {
return aa
}
func cube(a:Float) ->Float {
return aa*a
}
func averageSumOfSquare(a:Float, b:Float) ->Float {
return (square(a) + square(b))/2.0
}
func averageSumOfCube(a:Float, b:Float) ->Float {
return (cube(a) + cube(b)) / 2.0
}
averageSumOfSquare(1.0, b: 3.0)
averageSumOfCube(2.0, b: 3.0)
上面函数 `averageSumOfSquare` 和 `averageSumOfCube` 唯一不同之处就是分别调用了平方函数和立方函数。如果我们可以定义这样一个函数,这个函数以两个数和一个使用这两个数的函数作为参数,来计算平均值而不是重复调用将会非常好,我们可以使用闭包作为函数参数:
func averageOfSum(a:Float, b:Float, f:(Float ->Float)) ->Float {
return (f(a) + f(b))/2.0
}
averageOfSum(2.0, b: 3.0, f: square)
averageOfSum(3.0, b: 3.0, f: cube)
- `square`和`cube`可以被看做有名称的闭包
2. 无名称闭包
下面说一下无名内联闭包,代码也是写在大括号 `{}` 中,代码用 `in` 将参数和返回类型与实现(`body`)隔开:
// 注意格式,每一行换行的地方
individualScores.map({
(number:Int) ->Int in
let result = number+3
return result
})
3. 闭包简写
如果闭包的类型是已知的,比如 `delegate`,那么可以删掉闭包的`参数类型`或`返回类型`,或者两者都删掉。单语句闭包隐式返回这条语句的执行结果.
individualScores.map({
number in number+3})
print(individualScores)
let mappedScores = individualScores.map({
number in number+3})
- 数组 `individualScores` 中的值没有变化,而是调用 `.map` 之后会返回一个新的数组,新数组`mappedScores`中的值会每个都加3
我们还可以忽略参数名,使用默认参数名`$0`,如果有多个参数,使用 `$n` 作为第 `n-1` 个参数:
individualScores.map({
$0+3})
如果某一个函数的最后一个参数是闭包,那么这个闭包可以直接出现在圆括号`()`之后,例如下面的升序排序:
let sortedNumbers = individualScores.sort(){
$0 < $1
}
print(sortedNumbers)
如果某一个函数唯一的参数是闭包,那么可以把圆括号`()`省略掉:
let sortedNumbers = individualScores.sort {
$0 < $1
}
print(sortedNumbers)
4. 总结
>闭包是函数的一种,但闭包的真正意义是:把参数传递进一个块(这个块是用来实现闭包的),然后对参数就行修改,修改过之后,再使用。总结为一句话,传递参数-->修改-->使用