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)
}
}
昨天我更新到新的 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)
}
}