Swift 基本语法(五)— 函数闭包

2019-10-04  本文已影响0人  Eddiegooo

函数和闭包

函数基本定义与使用。 可以有一个或者多个参数,可以有一个返回值,也可以有多个返回值。函数是引用类型。

//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] //非空元素的个数
上一篇下一篇

猜你喜欢

热点阅读