Swift中@escaping的理解与使用

当我们在一个方法中将一个闭包当做参数的时候,那么就有很大概率用到这个@escaping关键字了,试想一般什么时候会将闭包当做参数传进来呢?很多时候比如方法里面有异步操作,需要方法先return,最后再调用闭包返回结果,如果直接通过return返回结果,那么传进来闭包也没什么用途了。

挑主要的说@escaping关键字修饰的闭包,意味着该闭包将在超出或离开你传递给它的作用域后仍然存在。也就是说这个闭包超出了方法的作用域,方法都return结束了,闭包还活着。
而没有被@escaping关键字修饰的闭包在方法结束的时候,也结束了自己。

首先先看一个没有@escaping关键字修饰的闭包。

func executeSomeRequest(_ closure: () -> Void) {
    closure()
}

上面这个方法是可以编译通过的,在executeSomeRequest方法中,直接调用了closure()闭包,然后方法执行完毕,闭包在方法的生命周期内执行完毕。

那么如果闭包没有在方法的生命周期内执行完毕,比如延迟执行闭包。

func executeSomeRequest(_ closure: () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
        closure()
    }
}

结果得到下面的报错:
在这里插入图片描述
报错是因为编译器认为传入的闭包将会超出方法的作用域,如果我们将让闭包超出方法的作用域,则需要使用@escaping关键字修饰闭包,这种闭包很多人称之为“逃逸闭包”,同时也会告知方法调用者,这里的闭包会超出方法的作用域,需要注意点。

修改后:

func executeSomeRequest(_ closure: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
        closure()
    }
}

还有一种比较常用场景就是在请求数据的时候,比如下面这种:

func requestData(_ completion: @escaping (Data?, NetworkError?) -> Void) {
    URLSession.shared.dataTask(with: URLRequest(url: URL(string: "https://xxxx")!)) { data, response, error in
        if let data {
            completion(data, nil)
        } else {
            completion(nil, .feedError("something wrong"))
        }
    }
}

requestData方法中发送了请求出去,然后在数据回来后调用传入的completion闭包,那么这个completion闭包肯定超出了方法的作用域,所以必须得用@escaping修饰。

除了上面说的这种情况,还有一种情况,比如我们用一个属性将传入进来的闭包保存了,待某个时候再调用,比如下面的用法,如果不加@escaping关键字,肯定会报错。

func requestData2(_ completion: @escaping (Data?, NetworkError?) -> Void) {
    self.completion = completion
}

总而言之,@escaping告诉方法调用者,这个闭包的的存活时间比方法要长,在内存的某个地方存储着,需要注意循环引用和内存泄漏。

使用逃逸闭包的优缺点:
优点:@escaping闭包提供了处理异步任务和回调的灵活性,尤其是在异步编程中。
缺点:@escaping闭包可以捕获并保持引用,如果处理不当,它们可能会创建强引用循环,从而导致内存泄漏。

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值