闭包-- 回调函数---Closures
闭包表达式语法
{ (parameters) -> return type in
statements
}
小练习:
///没有返回参数和返回值的闭包,好像匿名函数呀
let learn = {
print("练习闭包")
}
///带有参数的闭包
///in 关键字在闭包中,用来隔离参数返回值 和 函数体
let learn1 = { (lan: String) in
print("练习\(lan)")
}
///带有参数和返回值的闭包
let learn2 = { (lan: String) -> String in
return "练习\(lan)"
}
learn()
learn1("闭包")
let le = learn2("闭包")
print(le)
/**
练习闭包
练习闭包
练习闭包
*/
把鼠标放到learn
上显示问号的时候,按住option
点击.会显示,这是一个闭包:
闭包作为参数
///无参数,无返回值
func findWork(wo: ()->Void) {
print("1111")
wo()
print("2222")
}
///有参数无返回值(参数在闭包里面直接写类型)
func findWork1(wo: (String) -> Void) {
print("333")
wo("练习闭包")
print("444")
}
///有参数有返回值
func findWord2(wo: (String) -> String) {
print("555")
let w1 = wo("练习闭包")
print(w1)
print("666")
}
findWork(wo: learn)
findWork1(wo: learn1)
findWord2(wo: learn2)
/**
1111
练习闭包
2222
333
练习练习闭包
444
555
练习练习闭包
666
*/
尾随闭包 trailing closure
当最后一个参数是闭包的时候,就叫尾随闭包.也是唯一的要求.
上面的三个都可以调用方式变一下,变的更加简洁和简单. 上面的会有点繁琐,还需要额外定义一个闭包. 没有必要.swift中尾随闭包用的很多.
上面的调用也可以这样写:
findWork {
print("练习闭包1")
}
findWork1 { (lear) in
print("121212")
}
findWord2 { (lear) -> String in
"我们哎\(lear)"
}
/**
1111
练习闭包1
2222
333
121212
444
555
我们哎练习闭包
666
*/
嗯嗯,不用额外定义闭包,直接在尾随闭包中就把原先外面定义的闭包里面的内容写了.
$0
在看别人代码的时候会经常看到 $0
这种符号.这是干什么用的呢.其实就是闭包中的参数, 1 代表第二个参数,看实际例子:
用上面的 findwork1
方法来做例子:
///原先
findWork1 { (lear) in
print("findwordk1")
}
///使用 $0
findWork1 {
print("$0 = \($0)")
}
其实就是把 参数和in关键字给省略,直接使用 $ 符号来获取参数的一种形式.
/**
33
findwordk1
444
333
$0 = 练习闭包
444
*/
闭包作为返回值
闭包也是可以作为返回值的,在很多库中很常见.理解语法加深印象.
//可以看到闭包作为返回值,其实就是和闭包语法一样. 当看到两个 -> 我第一眼是很懵逼的. 这TMD是啥,当理解了之后你会发现. 这真TMD好用.
//这里采用的是 $0 的方式来获取的参数值.当时也可以使用 闭包表达式的方式
func findWork3() -> (String) -> Void {
return {
print("复习swift知识点\($0)")
}
}
//采用闭包表达式
func findWork4() -> (String) -> Void {
return { (str) in
print("复习swift知识点\(str)")
}
}
两种都需要理解. 一看就明白,要不你会看不懂很多库.
调用:
let result = findWork3()
result("态度哥哥")
let result1 = findWork4()
result1("态度哥哥")
/""
复习swift知识点态度哥哥
复习swift知识点态度哥哥
"/
返回值是闭包,说明返回的是一个函数. 你赋值的时候得到的也是函数. 所以使用的时候也是函数. 不过就是函数返回函数.
闭包捕获
啥叫捕获,就是你逮住一条狗了,或者逮住一条鱼了。 狗动你也动,狗不动你也不动 ... 好好理解下,狗就是你,你就是 ....
看代码,其实就是一个值,改变的时候在闭包中也会跟着变。
func findWork5() -> (String) -> Void {
var counter = 1
return {
print("\($0)在复习swift\(counter)")
counter += 1
}
}
let result = findWork5()
result("态度")
result("态度")
result("态度")
result("态度")
/**
态度在复习swift - 1
态度在复习swift - 2
态度在复习swift - 3
态度在复习swift - 4
*/
看上面counter的值一直是1,但是在闭包中,我们改变了这个值,所有下次的时候他就会增加.
逃逸闭包 @escaping
啥是逃逸,就是开车撞了,逃跑了 ...
当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。
关键字: @escaping
看定义中的就是 闭包在函数返回之后才被执行. 经常用在网络请求中. 下面的例子是我在项目中使用的.
let disposeBag = DisposeBag()
/// 修改手机号
/// - Parameters:
/// - old: 旧验证码
/// - new: 新验证码
/// - phone: 新手机
/// - completionHandler:
func changeLoginAccountPhone(old: String, new: String, phone: String,completionHandler:@escaping () -> ()){
SVProgressHUD.show(withStatus: "加载中...")
Provider.rx.request( .modifyPhone(oldVerifyCode: old, newVerifyCode: new, newLoginAccount: phone))
.asObservable()
.mapModel(ResponseData<String>.self)
.subscribe(onNext: { (model) in
SVProgressHUD.dismiss()
if model.code == Success {
completionHandler()
}
}).disposed(by: disposeBag)
}
viewModelPhone.changeLoginAccountPhone(old: oldCodeField.text!, new: newCodeField.text!, phone: newPhoneFiedl.text!) {
self.navigationController?.popViewController()
}
自动闭包 @autoclosure
自动的意思就是你写上关键字,他就自己给你把改做的做了。
自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。这种便利语法让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。
我感觉这一整段话都要理解:
自不返能用
自动创建的闭包、
不接受任何参数的闭包、
返回包装在里面的表达式的闭包、
能省略闭包的花括号的闭包、
用普通的表达式替换显示式的闭包。
看着很高大上....
看看列子:
//接受一个闭包,当闭包执行结果为true的时候进行打印
func logIfTrue(_ predicate: () -> Bool) {
if predicate() {
print("True")
}
}
//调用
logIfTrue({return 2 > 1})
logIfTrue({3 > 1})
logIfTrue{ 2 > 1 }
//使用 @autoclosure
func logIfTrue1(_ predicate: @autoclosure () -> Bool) {
if predicate() {
print("True")
}
}
//调用
logIfTrue1(2 > 1)
//Swift 将会把 2 > 1 这个表达式⾃动转换为 () -> Bool 。这样我们就得到了⼀个 写法简单,表意清楚的式⼦。
网友评论