Swift3 的许多问题:无法理解完成处理程序的新语法

Many problems with Swift3: cannot understand new syntax for completion handlers

昨天我更新到新的 Mac OS X Sierra 和 XCode 8 这迫使我更新到 Swift 3.0 语法。在我的应用程序中,我有很多功能,如下所示:

fileprivate func requestFisheFieldWithHandler(_ url:String, completionHandler: @escaping (_ success: NSDictionary?, _ error: NSError?) -> Void) {

    let configuration = URLSessionConfiguration.default

    let url: URL = URL(string: url)!
    let urlRequest: URLRequest = URLRequest(url: url)

    let session = URLSession(configuration: configuration)

    let task = session.dataTask(with: urlRequest, completionHandler: { (data: Foundation.Data?, response: URLResponse?, error: NSError?) -> Void in

        if (error != nil) {
            //print(error?.code)
            //print(error)
            completionHandler(success: nil, error: error)
        }

        else {
            do {
                let responseJSON = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) as! [String: String]
                completionHandler(success: responseJSON, error:nil)
            }
            catch let error as NSError {
                completionHandler(success: nil, error:error)
            }
        }
    } as! (Data?, URLResponse?, Error?) -> Void)

    task.resume()
}

我得到这个错误:

"Cannot convert value of type '(Data?, URLResponse?, Error?) -> Void' to expected argument type '(Data?, URLResponse?, Error?) -> Void'"

此外,我还使用了很多关联数组从下载的JSON文件中收集数据,如下所示:

for comune in response! {
                        self.comuni.append(comune["nome"] as! String)
                        self.comuniWithID[comune["nome"] as! String] = Int(comune["idcomune"] as! String)
}
DispatchQueue.main.async {
    self.myPicker.reloadComponent(1)
}

我得到的另一个错误是:

"Type 'NSFastEnumerationIterator.Element' (aka 'Any') has no subscript members"

拜托,有人可以帮我改正吗?因为我不明白他们的意思,我的应用程序将在明年 9 月 30 日发布...

最显着的变化是闭包中的所有参数标签已在 Swift 3.

中删除

这是您的代码 Swift 3 兼容。

一如既往,不要将 Swift 集合类型转换为 Foundation 对应物。您将丢弃所有类型信息。

并且不要在完成块 return 值中使用注释,编译器可以推断类型。如果您需要查找实际类型 ⌥-单击符号上的

fileprivate func requestFisheFieldWithHandler(_ url:String, completionHandler: @escaping ([String: String]?, NSError?) -> Void) {

  let configuration = URLSessionConfiguration.default

  let url: URL = URL(string: url)!
  let urlRequest = URLRequest(url: url)

  let session = URLSession(configuration: configuration)

  let task = session.dataTask(with: urlRequest) { (data, response, error) -> Void in
    if (error != nil) {
      completionHandler(nil, error as NSError?)
    }

    else {
      do {
        let responseJSON = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) as! [String: String]
        completionHandler(responseJSON, nil)
      }
      catch let error as NSError {
        completionHandler(nil, error)
      }
    }
  }
  task.resume()
}

关于第二个错误,你必须将 response! 转换为比 Any 更有意义的东西,我猜 ... in response as! [[String:Any]]

Swift 3 中 dataTask(with:completionHandler:) 的完成处理程序更改为 completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void,因此使用 Error 而不是 NSError

let task = session.dataTask(with: urlRequest, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in

有关完成处理程序检查的更多信息 Apple Documentation

对于你的错误

Type 'NSFastEnumerationIterator.Element' (aka 'Any') has no subscript members"

您需要指定您对 [[String:Any]] 的回复类型,然后一切正常。

if let array = response as? [[String: Any]] {
    for comune in array {
        self.comuni.append(comune["nome"] as! String)
        self.comuniWithID[comune["nome"] as! String] = Int(comune["idcomune"] as! String)
    }
}