关闭使用非转义参数可以允许它转义 [英] Closure use of non-escaping parameter may allow it to escape

查看:943
本文介绍了关闭使用非转义参数可以允许它转义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个协议:

enum DataFetchResult {
    case success(data: Data)
    case failure
}

protocol DataServiceType {
    func fetchData(location: String, completion: (DataFetchResult) -> (Void))
    func cachedData(location: String) -> Data?
}

使用示例实现:

    /// An implementation of DataServiceType protocol returning predefined results using arbitrary queue for asynchronyous mechanisms.
    /// Dedicated to be used in various tests (Unit Tests).
    class DataMockService: DataServiceType {

        var result      : DataFetchResult
        var async       : Bool = true
        var queue       : DispatchQueue = DispatchQueue.global(qos: .background)
        var cachedData  : Data? = nil

        init(result : DataFetchResult) {
            self.result = result
        }

        func cachedData(location: String) -> Data? {
            switch self.result {
            case .success(let data):
                return data
            default:
                return nil
            }
        }

        func fetchData(location: String, completion: (DataFetchResult) -> (Void)) {

            // Returning result on arbitrary queue should be tested,
            // so we can check if client can work with any (even worse) implementation:

            if async == true {
                queue.async { [weak self ] in
                    guard let weakSelf = self else { return }

                    // This line produces compiler error: 
                    // "Closure use of non-escaping parameter 'completion' may allow it to escape"
                    completion(weakSelf.result)
                }
            } else {
               completion(self.result)
            }
        }
    }

上面的代码在Swift3(Xcode8-beta5)中编译和工作,但不再使用beta 6。

The code above compiled and worked in Swift3 (Xcode8-beta5) but does not work with beta 6 anymore. Can you point me to the underlying cause?

推荐答案

这是因为函数参数的默认行为发生了变化。在Swift 3(特别是Xcode 8 beta 6附带的版本)之前,他们默认使用转义 - 你必须将它们标记为 @noescape ,以防止它们

This is due to a change in the default behaviour for function parameters. Prior to Swift 3 (specifically the build that ships with Xcode 8 beta 6), they would default to escaping – you would have to mark them as @noescape in order to prevent them from being stored or captured, therefore guaranteeing they won't be called after the function exits.

但是,现在 @noescape 是默认值 - 现在必须将函数参数标记为 @escaping ,告诉编译器它们可以被存储或捕获。

However, now @noescape is the default – you now have to mark function parameters as @escaping to tell the compiler that they can be stored or captured.

protocol DataServiceType {
    func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void)
    func cachedData(location: String) -> Data?
}

func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void) {
    // ...
}

请参阅Swift Evolution提案以获取有关此更改的更多信息。

See the Swift Evolution proposal for more info about this change.

这篇关于关闭使用非转义参数可以允许它转义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆