swift3.0中@escaping 和 @noescape 的含义

第一次翻译,嘿嘿
What Do @escaping and @noescape Mean In Swift 3

开始用swift语言是很容易的,而且它确实是一门很吸引人的语言。但是随着你频繁的使用,你会逐渐接触到swift更加复杂的结构.

在swift2中,你可能遇到过@noescape属性,你有没有花一点时间去理解它的意思?在swift3.0中,@noescape已经被移除了。为什么会这样?为什么swift3.0会引入@escaping?回答这些问题将成为这篇文章的主题。

@noescape的含义

即使@noescape在swift3.0中已经被废弃了,但是对于理解它的含义依然有用。为什么呢?很简单,在swift3.0中@noescape被用作一个默认值,让我们开始进一步研究吧。

什么是逃逸闭包(Escaping Closure)

首先你需要理解什么是逃逸闭包。它的定义非常简单而且易于理解。如果一个闭包被作为一个参数传递给一个函数,并且在函数return之后才被唤起执行,那么这个闭包是逃逸闭包。并且这个闭包的参数是可以“逃出”这个函数体外的。理解了这个定义,这个逃逸闭包是不是就很好理解了呢?

If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping.

在swift2中,你可以标记一个函数参数@noescape属性,来告诉编译器传递给这个函数的闭包不允许“逃逸”出函数体外,让我们看一下下面的例子,注意这是用swift2写的。

import HealthKit

class HealthKitManager: NSObject {

    private let healthStore = HKHealthStore()

    func requestAuthorization(completion: (Bool, NSError?) -> Void) {
        var shareTypes = Set<HKSampleType>()
        var readTypes = Set<HKSampleType>()

        // Add Workout Type
        shareTypes.insert(HKSampleType.workoutType())
        readTypes.insert(HKSampleType.workoutType())

        // Request Authorization
        healthStore.requestAuthorizationToShareTypes(shareTypes, readTypes: readTypes,completion: completion)
    }

}

可以看到requestAuthorization(_:)方法接收了一个参数:一个闭包。在swift2中,闭包默认是可以“逃逸”到函数体外的,这就是为什么上面的例子没有报编译错误。注意completion作为一个参数传递给HKHealthStorerequestAuthorizationToShareTypes(_:readTypes:completion:)方法,这个方法是异步的,也就是说这个闭包会在requestAuthorization(_:)函数return之后执行。换句话说,我们传给requestAuthorization(_:)的这个闭包逃逸了,它已经逃逸出了这个函数体。

如果我们给requestAuthorization(_:)函数参数添加一个@noescape属性会变得非常有趣,下面是添加@noescape属性的例子

import HealthKit

class HealthKitManager: NSObject {

    private let healthStore = HKHealthStore()

    func requestAuthorization(@noescape completion: (Bool, NSError?) -> Void) {
        var shareTypes = Set<HKSampleType>()
        var readTypes = Set<HKSampleType>()

        // Add Workout Type
        shareTypes.insert(HKSampleType.workoutType())
        readTypes.insert(HKSampleType.workoutType())

        // Request Authorization
        healthStore.requestAuthorizationToShareTypes(shareTypes, readTypes: readTypes,completion: completion)
    }
}

我们直接告诉编译器这个completion参数不能逃逸出函数体外,结果就是编译报错,并解释了是什么错误

这里写图片描述

swift3.0

下面给出上面例子的swift3版本。这个例子会展示“逃逸闭包”在swift3.0会有什么变化。

import HealthKit

class HealthKitManager: NSObject {

    private let healthStore = HKHealthStore()

    func requestAuthorization(@noescape completion: (Bool, Error?) -> Void) {
        var shareTypes = Set<HKSampleType>()
        var readTypes = Set<HKSampleType>()

        // Add Workout Type
        shareTypes.insert(HKSampleType.workoutType())
        readTypes.insert(HKSampleType.workoutType())

        // Request Authorization
        healthStore.requestAuthorization(toShare: shareTypes, read: readTypes, completion: completion)
    }

}

编译器立即告诉我们@noescape在swift3中是默认的并且建议移除@noescape。事实上,@noescape在swift3中已经被废弃,你以后都不会用到它了。

这里写图片描述

因为我们传递给requestAuthorization(completion:)注意这个方法签名在swift3变得不一样了)函数的闭包逃逸了,所以我们需要标记这个参数escaping.我们使用一个新的属性@escaping。这是SE-0103的直接结果,一个swift的进化理论提出默认创建不可逃逸的闭包。这是一个非常受欢迎的改变如果你问我的话。

import HealthKit

class HealthKitManager: NSObject {

    private let healthStore = HKHealthStore()

    func requestAuthorization(completion: @escaping (Bool, Error?) -> Void) {
        var shareTypes = Set<HKSampleType>()
        var readTypes = Set<HKSampleType>()

        // Add Workout Type
        shareTypes.insert(HKSampleType.workoutType())
        readTypes.insert(HKSampleType.workoutType())

        // Request Authorization
        healthStore.requestAuthorization(toShare: shareTypes, read: readTypes, completion: completion)
    }

}

这里写图片描述

你可能注意到了,这个@escaping属性写在参数类型的前面而不是参数名称的前面。这是swift3里一个新的点。

@escaping的含义

这个提醒我们去理解@escaping属性的含义。因为在swift3中闭包默认是不可逃逸的,逃逸闭包需要像这样被标记。@escaping属性让我们可以那样做。

我们通过@escaping属性标记闭包,编译错误就消失了。

重点

这里几点关于创建默认不可逃逸闭包的好处: 最明显的好处就是编译器优化你的代码的性能和能力。如果编译器知道这个闭包是不可逃逸的,它可以关注内存管理的关键细节。

而且你可以在不可逃逸闭包里放心的使用self关键字,因为这个闭包总是在函数return之前执行,你不需要去使用一个弱引用去引用self.这对你而言是一个非常nice的功能。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值