美文网首页
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 - 闭包

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