【问题标题】:Invalid conversion from throwing function of type (_,_,_) throws -> Void to non-throwing function type (NSData?, NSURLResponse?, NSError?) -> Void从类型 (_,_,_) throws -> Void 到非抛出函数类型 (NSData?, NSURLResponse?, NSError?) -> Void 的无效转换
【发布时间】:2015-12-24 08:35:47
【问题描述】:

我已经写了这段代码:

func getjson() {
        let urlPath = "https://api.whitehouse.gov/v1/petitions.json?limit=100"
        let url = NSURL(string: urlPath)
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
            print("Task completed")
            if(error != nil) {
                print(error!.localizedDescription)
            }
            let err: NSError?
            if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary {
                if(err != nil) {
                    print("JSON Error \(err!.localizedDescription)")
                }
                if let results: NSArray = jsonResult["results"] as? NSArray {
                    dispatch_async(dispatch_get_main_queue(), {
                        self.tableData = results
                        self.Indextableview.reloadData()
                    })
                }
            }
        })

        task.resume()

    }

更新到 XCode 7 后,它给了我这个错误:从 (_, _, _) 类型的抛出函数抛出的无效转换 -> Void 到非抛出函数类型 (NSData?, NSURLResponse?, NSError?) - > 无效。排队了,让任务在哪里。

谢谢

【问题讨论】:

  • 指出导致问题的行并使用完整准确的错误消息更新您的问题。
  • 但是我应该在哪里使用try? @LeoDabus
  • 在尝试添加成功后应该运行的代码后进行尝试
  • 我已经更新了完整的错误消息@rmaddy
  • 尝试代码已在非 try-catch 块中使用。它发生在我身上。通过将 try xxx 更改为 try? xxx 来修复它

标签: ios swift try-catch urlsession json-serialization


【解决方案1】:

您需要按如下方式实现 Do Try Catch 错误处理:

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

extension URL {
    func asyncDownload(completion: @escaping (_ data: Data?, _ response: URLResponse?, _ error: Error?) -> ()) {
        URLSession.shared
            .dataTask(with: self, completionHandler: completion)
            .resume()
    }
}

let jsonURL = URL(string: "https://api.whitehouse.gov/v1/petitions.json?limit=100")!
let start = Date()
jsonURL.asyncDownload { data, response, error in

    print("Download ended:", Date().description(with: .current))
    print("Elapsed Time:", Date().timeIntervalSince(start), terminator: " seconds\n")
    print("Data size:", data?.count ?? "nil", terminator: " bytes\n\n")

    guard let data = data else {
        print("URLSession dataTask error:", error ?? "nil")
        return
    }

    do {
        let jsonObject = try JSONSerialization.jsonObject(with: data)
        if let dictionary = jsonObject as? [String: Any],
            let results = dictionary["results"] as? [[String: Any]] {
            DispatchQueue.main.async {
                results.forEach { print($0["body"] ?? "", terminator: "\n\n") }
      //        self.tableData = results
      //        self.Indextableview.reloadData()
            }
        }
    } catch {
        print("JSONSerialization error:", error)
    }
}
print("\nDownload started:", start.description(with: .current))

【讨论】:

  • 有没有办法让错误更上一层楼?因为我的“getjson”函数在一个单独的类中。而且我不想打印错误描述,而是在 UIAlertController 中向用户显示它。但是 UIAlertController 只能通过调用“getjson”函数的 UIViewController 显示。
  • @Adarkas2302 是一种异步方法,实现此目的的最简单方法是发布通知并将观察者添加到您需要显示警报的视图控制器。 stackoverflow.com/a/30541063/2303865
【解决方案2】:

正如 Leo 所建议的,您的问题是您使用的是 try,但不在 do-try-catch 构造中,这意味着它推断出闭包被定义为抛出错误,但由于它没有这样定义,你会得到那个错误。

所以,添加do-try-catch:

func getjson() {
    let urlPath = "https://api.whitehouse.gov/v1/petitions.json?limit=100"
    let url = URL(string: urlPath)!
    let session = URLSession.shared
    let task = session.dataTask(with: url) { data, response, error in
        print("Task completed")

        guard let data = data, error == nil else {
            print(error?.localizedDescription)
            return
        }

        do {
            if let jsonResult = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
                if let results = jsonResult["results"] as? [Any] {
                    DispatchQueue.main.async {
                        self.tableData = results
                        self.indexTableView.reloadData()
                    }
                }
            }
        } catch let parseError {
            print("JSON Error \(parseError.localizedDescription)")
        }
    }

    task.resume()
}

【讨论】:

    【解决方案3】:

    在 Swift 2 中,将所有 NSError 替换为 ErrorType

    试试这个。

      class func fetchWeatherForLocation(locationCode: String = "", shouldShowHUD: Bool = false, completionHandler: (data: NSDictionary?, error: ErrorType?) -> ()) {
    
    
    
        let url = NSURL(string: "myurl")               
        let task =  NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
    
            if let dataWithKey = data {
    
                do {
                    let jsonForDataWithTemprature = try NSJSONSerialization.JSONObjectWithData(dataWithKey, options:NSJSONReadingOptions.MutableContainers)
    
                    guard let arrayForDataWithKey :NSArray = jsonForDataWithTemprature as? NSArray else {
                        print("Not a Dictionary")
                        return
                    }
    
                    let dictionaryWithTemprature = arrayForDataWithKey.firstObject as! NSDictionary
    
                    completionHandler(data: dictionaryWithTemprature, error: nil)
    
                }
                catch let JSONError as ErrorType {
                    print("\(JSONError)")
                }
    
            }
        }
    
        task.resume()
    }
    

    【讨论】:

      【解决方案4】:

      更改代码 try-catch 中的错误类型对我有用。

      "将所有 NSError 替换为 ErrorType"

      【讨论】:

        猜你喜欢
        • 2016-08-19
        • 2016-08-14
        • 1970-01-01
        • 2018-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多