美文网首页
Swift - 闭包

Swift - 闭包

作者: 态度哥 | 来源:发表于2020-11-05 15:07 被阅读0次

语雀地址

闭包-- 回调函数---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点击.会显示,这是一个闭包:

image.png image.png image.png

闭包作为参数

///无参数,无返回值
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 这种符号.这是干什么用的呢.其实就是闭包中的参数, 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 。这样我们就得到了⼀个 写法简单,表意清楚的式⼦。

相关文章

  • Swift-闭包

    Swift 闭包 函数 ()->() Swift 中的闭包和 Objective-C 中的 block 类似,闭包...

  • Swift闭包和函数

    函数在Swift中只是一种特殊的闭包,闭包在Swift语言中是一等公民,支持闭包嵌套和闭包传递。Swift中的闭包...

  • swift4 闭包

    swift 闭包 闭包:swift 中 函数是闭包的一种类似于oc的闭包闭包表达式(匿名函数) -- 能够捕获上下...

  • Swift中的闭包

    在Swift中有两种闭包,逃逸闭包(@escaping)和非逃逸闭包(@nonescaping)。从Swift 3...

  • 100 Days of Swift - Day 06 - 闭包(

    100 Days of Swift - Day 06 - 闭包Closures 6.1 闭包 Swift函数也属于...

  • swift学习

    * 闭包 * 闭包作为属性 ```swift // 声明闭包类型 typealias callba...

  • iOS swift 逃逸闭包(@escaping)和非逃逸闭

    iOS swift 逃逸闭包(@escaping)和非逃逸闭包 (@noescaping) 逃逸闭包: 逃逸闭包...

  • iOS&Swift&OC 闭包和Block的相互转化

    一、Swift的闭包 -> OC的block 二、OC的block -> Swift的闭包

  • swift闭包学习

    闭包作为参数 参考 Swift学习之闭包

  • Swift学习笔记(1)

    SWift学习笔记 闭包 闭包表达式 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 ...

网友评论

      本文标题:Swift - 闭包

      本文链接:https://www.haomeiwen.com/subject/cgzovktx.html