swift中闭包的详细教程-白话说

1. 逃逸闭包的概念及使用

这个名字看着挺高大上的,我个人总结就一句话:不同步使用闭包参数,以异步方式再次使用时,是逃逸闭包。

也就是说 - 做为函数参数的闭包,在函数被调用时没有马上执行,而是把他存下来了,等待着某个时机到达的时候, 再去执行这个闭包。

var funHandler: ()->Void = {print("nothing.")};
func bindFunClosure(Closure c: @escaping ()->Void){
    funHandler = c;
}
bindFunClosure(Closure :{print("i'm from escaping closure.")});
funHandler();

输出结果为:

i'm from escaping closure.

对于逃逸闭包你想做错都不能,因为编译器会直接给你准确的提示,要求你加上 @escaping , 如下图所示。
在这里插入图片描述

2. 尾随闭包的概念及使用

如果你用过scala语言基于spark做大数据开发的经验,那么这个列子将极好理解,统计单词的出现我的次数中的一个步骤就是将 word 变为 (word,1)

var arr:[String] = ["abc","ace","dac","aee","cfa","abb","bac","baa"];
let arrChange = arr.map({ (value) -> (String,Int) in
    return (value,1);
})
print(arrChange);

输出结果为:

[("abc", 1), ("ace", 1), ("dac", 1), ("aee", 1), ("cfa", 1), ("abb", 1), ("bac", 1), ("baa", 1)]

3. 闭包外部变量引用-捕获值

一个闭包能够从上下文捕获已被定义的常量和变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍能够在其函数体内引用和修改这些值。—捕获值。

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0;
    func incrementer()->Int{
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
let incrementBySeven = makeIncrementer(forIncrement: 7)
print(incrementByTen())
print(incrementByTen())
print(incrementBySeven())
print(incrementByTen(), terminator: "")

输出结果为:

10
20
7
30

在上面例子中, incrementBySeven 和 incrementByTen 是常量,但是这些常量指向的闭包仍可以增加已捕获的变量 runningTotal 的值。这是因为函数和闭包都是引用类型

4. 闭包实现的排序

extension Array {
    mutating func sortEX(by:(Element,Element) throws ->  Bool) rethrows {
        let count = self.count;
        var idx = 0;
        for i in 0..<count { //0...count-1
            idx = i;
            for j in i..<count {
                if(try by(self[idx],self[j])){
                    idx = j;
                }
            }
            let a = self[i];
            self[i] = self[idx];
            self[idx] = a;
        }
    }
}

var arr:[String] = ["abc","ace","dac","aee","cfa","abb","bac","baa"];
print(arr);
//下面三种方式实现的闭包,效果是一样的
//arr.sortEX(by: {(v1:String,v2:String)->Bool in return v1 > v2; })
//arr.sortEX(by: { $0 > $1 })
arr.sortEX(by: > )
print(arr);

输出结果为:

["abc", "ace", "dac", "aee", "cfa", "abb", "bac", "baa"]
["abb", "abc", "ace", "aee", "baa", "bac", "cfa", "dac"]

5. 自动闭包的概念及使用

一张图片,说明问题,run1无法将一个语句转为闭包,但是 run2是可以的.
在这里插入图片描述
修改代码如下:

let say = {s in print(s)}

func run1(F f:()->Void){
    f();
}
func run2(F f:@autoclosure ()->Void){
    f()
}

run1(F:{say("first.")})
run2(F:say("second."))

输出结果为:

first.
second.

官方assert的函数定义如下:

/// * In `-O` builds (the default for Xcode's Release configuration),
///   `condition` is not evaluated, and there are no effects.
///
/// * In `-Ounchecked` builds, `condition` is not evaluated, but the optimizer
///   may assume that it *always* evaluates to `true`. Failure to satisfy that
///   assumption is a serious programming error.
///
/// - Parameters:
///   - condition: The condition to test. `condition` is only evaluated in
///     playgrounds and `-Onone` builds.
///   - message: A string to print if `condition` is evaluated to `false`. The
///     default is an empty string.
///   - file: The file name to print with `message` if the assertion fails. The
///     default is the file where `assert(_:_:file:line:)` is called.
///   - line: The line number to print along with `message` if the assertion
///     fails. The default is the line number where `assert(_:_:file:line:)`
///     is called.
public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuanwenchao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值