Invalid conversion from throwing function of type (_,_,_) throws -> Void to non-throwing function type (NSData?, NSURLResponse?, NSError?) -> Void

73,421

Solution 1

You need to implement Do Try Catch error handling as follow:

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))

Solution 2

As Leo suggested, your problem is that you're using try, but not within the do-try-catch construct, which means that it infers that the closure is defined to throwing the error, but since it is not defined as such, you get that error.

So, add 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()
}

Solution 3

In Swift 2, replace all NSError with ErrorType

Try this.

  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()
}
Share:
73,421

Related videos on Youtube

Martin Mikusovic
Author by

Martin Mikusovic

Updated on July 08, 2022

Comments

  • Martin Mikusovic
    Martin Mikusovic over 1 year

    I have written this code:

    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()
    
        }
    

    And after update to XCode 7 it gives me this error: Invalid conversion from throwing function of type (_, _, _) throws -> Void to non-throwing function type (NSData?, NSURLResponse?, NSError?) -> Void. It is in line, where is let task.

    Thanks

    • rmaddy
      rmaddy about 8 years
      Point out the line causing the issue and update your question with the complete and exact error message.
    • Martin Mikusovic
      Martin Mikusovic about 8 years
      But where should I use try? @LeoDabus
    • Leo Dabus
      Leo Dabus about 8 years
      Do try after try add code that should run if successful
    • Martin Mikusovic
      Martin Mikusovic about 8 years
      I have updated complete error message @rmaddy
    • slboat
      slboat over 2 years
      try code been use in a not try-catch block.it's happen to me.fix it by change try xxx to try? xxx
  • Adarkas2302
    Adarkas2302 over 7 years
    Is there a way to hand the Error further up the chain? Because my "getjson" function is in a separate class. And i don't want to print the error description but show it in an UIAlertController to the user. But the UIAlertController can only be show from a UIViewController with calls the "getjson" function.
  • Leo Dabus
    Leo Dabus over 7 years
    @Adarkas2302 being an asynchronous method, the easiest way to accomplish this would be posting a notification and adding an observer to the view controller you need to display the alert. stackoverflow.com/a/30541063/2303865