【问题标题】:Swift: Escaping closure captures non-escaping parameter 'onCompletion'Swift:转义闭包捕获非转义参数“onCompletion”
【发布时间】:2020-05-04 04:48:39
【问题描述】:

我的 swift 有问题。我正在尝试发送 API 请求然后检索数据,但收到以下错误消息:

“Swift:转义闭包捕获非转义参数'onCompletion'”。

有谁知道我该如何解决这个问题?提前致谢

代码:


class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()
    
    let baseURL = "http://api.randomuser.me/"
    
    func getRandomUser(onCompletion : (JSON) -> Void) {
        makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
            onCompletion(json)
        })
    }
    
    func makeHTTPGetRequest(path: String, onCompletion: ServiceResponse) {
        let request = NSMutableURLRequest(url : URL(string: path)! as URL)
        
        let session = URLSession.shared
        
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            let json:JSON = JSON(data as Any)
            onCompletion(json, error as NSError?)
        })
        task.resume()
    
    }
}

【问题讨论】:

  • 检查这个:stackoverflow.com/a/46245943/5492956Escaping Closure: An escaping closure is a closure that’s called after the function it was passed to returns. In other words, it outlives the function it was passed to. Non-escaping closure: A closure that’s called within the function it was passed into, i.e. before it returns.

标签: ios swift api get


【解决方案1】:

您必须用@escaping 标记两个完成处理程序。通常编译器会提供修复

class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()

    let baseURL = "http://api.randomuser.me/"

    func getRandomUser(onCompletion : @escaping (JSON) -> Void) {
        makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
            onCompletion(json)
        })
    }

    func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse) {
        let request = NSMutableURLRequest(url : URL(string: path)! as URL)

        let session = URLSession.shared

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            let json:JSON = JSON(data as Any)
            onCompletion(json, error as NSError?)
        })
        task.resume()

    }
}

【讨论】:

    【解决方案2】:

    这里的答案是在完成处理程序参数声明之前添加@escaping,尽管有简短的解释。

    这是我缺少的完整图片,取自Swift's documentation

    转义闭包

    闭包被称为逃逸函数,当 闭包作为参数传递给函数,但在之后调用 函数返回。当你声明一个接受闭包的函数时 作为其参数之一,您可以在 参数的类型,表示允许闭包逃逸。

    所以基本上,如果您希望在方法返回后AFTER调用完成处理程序,它在swift中定义为escaping,并且应该这样声明:

    func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse)
    

    【讨论】:

      【解决方案3】:

      使用这个:

      class RestApiManager: NSObject {
      static let sharedInstance = RestApiManager()
      
      let baseURL = "http://api.randomuser.me/"
      
      func getRandomUser(onCompletion : @escaping (JSON) -> Void) {
          makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
              onCompletion(json)
          })
      }
      
      func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse) {
          let request = NSMutableURLRequest(url : URL(string: path)! as URL)
      
          let session = URLSession.shared
      
          let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
              let json:JSON = JSON(data as Any)
              onCompletion(json, error as NSError?)
          })
          task.resume()
      
      }
      }
      

      【讨论】:

        【解决方案4】:

        这是由于您的参数 onCompletion 而发生的。默认情况下它是@nonesacping,你必须将它标记为@esacping,以便它可以在completionHandler 闭包中工作。

        func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse)
        

        【讨论】:

          猜你喜欢
          • 2021-12-23
          • 1970-01-01
          • 2022-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-29
          • 2021-02-01
          相关资源
          最近更新 更多