函数和闭包
函数基本定义与使用。 可以有一个或者多个参数,可以有一个返回值,也可以有多个返回值。函数是引用类型。
//swift 5.1新特性,隐式返回值
func greet(person: String) -> String {
return "hello +\(person)" //单一表达式,在swift5.1中,可以省掉return, 直接返回"hello +\(person)"
}
//返回可选值类型
func minMaxTuple(nums: [Int]) ->(min: Int, max: Int)? {
if nums.count < 1 {
return nil //如果不是可选元组返回值类型,这里会报错
}
var min = nums[0]
var max = nums[0]
for value in nums {
if min > value {
min = value
}
if max < value {
max = value
}
}
return (min, max)
}
函数的实际参数和形式参数
func function(_ person: String, from hometown: String) {
/// person,hometown 形式参数名 ; from 实际参数标签。
/// 当有实际参数标签的时候,函数调用的时候就不会显示形式参数名。function(person: "Eddie", from: "China")
/// _ 通用实际参数标签,不指定。在调用函数的会有提示 function("Eddie", from: "China")
}
//也可以指定一个默认参数值,当有传参时,使用传的参数值,没有使用默认值
func defaultParamFunc(defaultParam: Int = 88, num: Int) {
print(defaultParam + num)
}
defaultParamFunc(defaultParam: 66, num: 4) // 66-->70
defaultParamFunc(num: 2) //88--->90
//可变形式参数
func addNums(nums: Int ...) -> Int{
var sum = 0
for num in nums {
sum += num
}
return sum
}
addNums(nums: 1,2,3,4,5)
//输入输出形式参数 关键字inout。 可以直接使用并且修改。 当使用它的时候,要在其前面加一个&符号。 传入的必须是变量。 不可以有默认值,可变形式参数不可以被标记为inout类型。
func swapTwoNums(num1: inout Int, num2: inout Int){
let temp = num1
num1 = num2
num2 = temp
}
var a = 3, b = 5
swapTwoNums(num1: &a, num2: &b)
print(a,b) // 5 3
函数类型.
//内嵌函数 封装隔离效果
func chooseStepFunction(forwardVale: Bool) -> (Int) -> Int {
func forwardStep(step: Int) -> Int { return step + 1}
func backWardStep(step: Int) -> Int { return step - 1}
return forwardVale ? forwardStep : backWardStep
}
var currentValue = 4
let stepFunc = chooseStepFunction(forwardVale: currentValue < 0)
while currentValue != 0 {
currentValue = stepFunc(currentValue)
}
//将函数当形式参数使用
func printFunctionResult(mathFunction:(Int, Int) -> (Int), _ a: Int, _ b: Int) {
print(mathFunction(a,b))
}
func addTwoNum(a: Int, b: Int) -> Int{
return a + b
}
printFunctionResult(mathFunction: addTwoNum, 3, 5)
闭包 和函数一样,也是引用类型
{ (参数,参数,...) -> returnType in
表达式
}
let nameArray = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
func compareName(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
let result = nameArray.sorted(by: compareName)
//print(result)
//直接使用闭包
let array = nameArray.sorted(by: {(s1: String, s2: String) -> Bool in
return s1 > s2
})
//单表达式, 可以省略返回值表达式写法
nameArray.sorted(by: {(s1: String, s2: String) -> Bool in
s1 > s2
})
//根据内容自推断类型,省略类型说明符
let simpleArray = nameArray.sorted(by: {(s1, s2) in
s1 > s2
})
nameArray.sorted { (s1, s2) -> Bool in
s1 > s2
}
nameArray.sorted{ s1, s2 in
s1 > s2
}
//运算符形式
nameArray.sorted(by: > )
//单表达式 尾随闭包
nameArray.sorted{ $0 > $1}
逃逸闭包和自动闭包
//逃逸闭包:函数调用结束后才去调用,就要标记为可逃逸的@escaping 自动闭包:@autoclosure
var names = ["Eddiegooo", "zhangsan", "lisi", "wangwu"]
var resultArray:[() -> String] = []
//会报错。。
//func someFunction(name: () -> String) {
// resultArray.append(name) //报错error: passing non-escaping parameter 'name' to function expecting an @escaping closure
//}
//可逃逸闭包
func someFunction(name: @escaping () -> String) {
resultArray.append(name)
}
//someFunction(name: "zhaoliu") //error: cannot convert value of type 'String' to expected argument type '() -> String'
someFunction(name: { "Eddie" })
//如果将闭包设置为自动闭包类型,调用时候可以直接传字符串
func someFunction1(name: @autoclosure @escaping () -> String) {
resultArray.append(name)
}
//逃逸闭包如果使用属性,必须显式使用self
class someClass {
var somename: String = "Chole"
func someFunc() {
someFunction(name: { self.somename })
}
}
高阶函数,主要就三个map, reduce, filter
//高阶函数
//map 函数。 给每一个元素都做同样的操作 得到一个新的数组
let nums = [1, 2, 4, 5]
let newNums = nums.map { $0 * 10 }
print(newNums) // [10, 20, 40, 50]
//filter条件筛选。 不符合的直接舍弃
print(nums.filter({ $0 > 3 })) //[4, 5]
//reduce 在一个初始值的基础上 累加所有元素
print(nums.reduce(30, { $0 + $1 })) //42 = 30+1+2+4+5
//直接合并成一组数据数组
let arrayNums = [[1,2,3], [4,5,6], [7,8,9]]
print(arrayNums.flatMap({$0.map({$0 * 10})})) // [10, 20, 30, 40, 50, 60, 70, 80, 90]
let nameArray: [String?] = ["zhangsan", nil, "lisi", "wangzu", nil]
print(nameArray.count) //5
print(nameArray.flatMap({ $0 })) == print(nameArray.compactMap({ $0 })) //["zhangsan", "lisi", "wangzu"] 获取非空元素新集合
print(nameArray.flatMap({ $0?.count })) //[8, 4, 6] //非空元素的个数