先复习一下函数Swift-func
闭包可以定义一个函数
闭包可以定义一个函数
闭包可以定义一个函数
闭包概念:
- 一个函数和它所捕获的变量/常量环境组合起来,称为闭包
- 一般指定义在函数内部的函数
- 一般它捕获的是外层函数的局部变量/常量
演绎过程:
typealias Fn = (Int) -> Int
func getFn() -> Fn {
var num = 10
func plus(i: Int) -> Int {
num += I
return num
}
return plus//这是函数哦 不能是实现
return plus(I:)
}
var fnx = getFn()
print(fnx(1))
- 2层函数 外层函数
getFn
返回值是函数类型 内层函数plus
也要返回函数类型 - plus函数和num形成了闭包
简易一下程序
func getFn() -> Fn {
var num = 10
return {
num += $0
return num
}
}
类比一个类的实例对象
- 内存在堆空间
- 捕获的局部变量/常量就是对象的成员(存储属性)
- 组成闭包的函数 就是类内部定义的方法
class Closure {
var num = 0
func plus(_ i:Int) -> Int {
num += I
return num
}
}
var cs1 = Closure()
print(cs1.plus(1))
闭包
Swift中,可以通过func定义一个函数 也可以通过闭包表达式定义一个函数
func add(_ v1: Int,_ v2: Int) -> Int {
v1 + v2
}
var fx = {
(v1: Int,v2: Int) -> Int in
return v1 + v2
}
print(fx(10,20))
print(fx)
print(add)
把实现带着随便测试
var fx1 = {
(v1: Int,v2: Int) -> Int in
return v1 + v2
}(10,10)
print(fx1)
- 上面打印
fx
打印结果:(Function)
- 上面打印
add
打印结果:(Function)
- 闭包类似add 然后调用它 传入参数fx(10,20)
闭包作为参数(闭包简写真特么简 其实不简写容易读)
//exec定义
func exec(v1: Int,v2: Int,fn:(Int,Int) -> Int) {
print(fn(v1,v2))
}
实现exec方法
- 普通函数
var fn:(Int,Int)->Int = add
exec(v1: 10, v2: 10, fn: fn)
- 闭包
//写全一点
exec(v1: 10, v2: 20, fn: {
(v1: Int,v2: Int) -> Int in
return v1 + v2
})
//省略return
exec(v1: 10, v2: 20, fn: {
(v1: Int,v2: Int) -> Int in
v1 + v2
})
//省略参数
exec(v1: 10, v2: 20, fn: {
v1,v2 -> Int in
v1 + v2
})
//省略返回值
exec(v1: 10, v2: 20, fn: {
v1,v2 in
v1 + v2
})
//下标
exec(v1: 10, v2: 10, fn: {
$0 + $1
})
//一步到位了靠
exec(v1: 10, v2: 10, fn: +)
尾随闭包
- 如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性
- 尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式
- 如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后面写圆括号
func exec1(fn:(Int,Int) -> Int) {
print(fn(1,2))
}
exec1(fn: {
(v1: Int,v2: Int) -> Int in
return v1 * v2
})
exec1{
(v1: Int,v2: Int) -> Int in
return v1 * v2
}
......下面同样可以省略 自己搞吧
自动闭包(语法真鸡贼)
后面在搞吧 语法真特么难懂太简易了
- @autoclosure 会自动将20 封装成闭包{20}
- @autoclosure 只支持 () -> T 格式的参数
- @autoclosure 并非只支持最后一个参数
- 空合并运算符?? 使用了@autoclosure技术
- 有@autoclosure 无@autoclosure,构成了函数重载
- 为了避免与期望冲突,使用了@autoclosure的地方最好明确注释清楚,这个值会被推迟执行
func getFirstPositive (_ v1: Int,_ v2: Int) -> Int {
return v1 > 0 ?v1 : v2
}
print(getFirstPositive(10, 20))
print(getFirstPositive(-2, 20))
print(getFirstPositive(0, -4))
//改成函数类型的参数,可以让v2延迟加载
func getFirstPositive(_ v1: Int,_ v2: () -> Int) -> Int? {
return v1 > 0 ? v1: v2()
}
print(getFirstPositive(-4, {20})!)
func getFirstPositive1(_ v1: Int,_ v2:@autoclosure () -> Int) -> Int? {
return v1 > 0 ? v1: v2()
}
print(getFirstPositive1(-4, 20)!)
参数修饰符保持一致
//如果返回值是函数类型,那么参数的修饰要保持统一
func total(_ num: Int) -> (inout Int) -> Void {
func plus(v: inout Int) {
v += num
}
return plus
}
var vvvv = 5
total(20)(&vvvv)
print(vvvv)
忽略参数(语法真鸡贼)
func exec2(fn:(Int ,Int) -> Int) {
print(fn(1,2))
}
exec2{_,_ in 100}
练习
var functions:[() -> Int] = []
for i in 1...3 {
functions.append{I}
}
for i in functions {
print(i)
}
class Closure2 {
var i: Int
init(_ i: Int) {
self.i = I
}
func get() -> Int {
return I
}
}
var clses:[Closure2] = []
for i in 1...3 {
clses.append(Closure2(i))
}
for i in clses {
print(i.get())
}
补充案例
案例一:网络请求 省略参数 逃逸闭包
Function types cannot have argument labels; use '_' before 'result'
从Swift3.0开始, 苹果官方建议方法中函数类型的参数不要带参数名称, 尤其是不能带外部参数名.
解决方案:
- 省略标签参数
- 这个闭包里面的标签参数是为了增加代码可读性
class func requestData(parameters: [String:Any]?,finishedCallBack:(_ result:Any)->()) {
finishedCallBack("回调请求内容")
}
新的问题
逃逸闭包捕获非逃逸闭包
captures:捕获
Escaping:逃逸
语法小计
- 闭包实现 可以把参数省略
NetworkTools.requestData(url: requestUrl, method: .post, parameters: parameters) { response, status in
}
NetworkTools.requestData(url: requestUrl, method: .post, parameters: parameters) { (response, status) in
}