168

Hello I have working json parsing code for swift2.2 but when i use it for Swift 3.0 gives me that error

ViewController.swift:132:31: Ambiguous reference to member 'dataTask(with:completionHandler:)'

My code is here:

   let listUrlString =  "http://bla.com?batchSize=" + String(batchSize) + "&fromIndex=" + String(fromIndex)
    let myUrl = URL(string: listUrlString);
    let request = NSMutableURLRequest(url:myUrl!);
    request.httpMethod = "GET";
    
    let task = URLSession.shared().dataTask(with: request) {
        data, response, error in
        
        if error != nil {
            print(error!.localizedDescription)
            DispatchQueue.main.sync(execute: {
                AWLoader.hide()
            })
            
            return
        }
        
        do {
            
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray
            
            if let parseJSON = json {
                
                var items = self.categoryList
                
                items.append(contentsOf: parseJSON as! [String])
                
                if self.fromIndex < items.count {
                    
                    self.categoryList = items
                    self.fromIndex = items.count
                    
                    DispatchQueue.main.async(execute: {
                        
                        self.categoriesTableView.reloadData()
                        
                        AWLoader.hide()
                        
                    })
                }else if( self.fromIndex == items.count){
                    
                    
                    DispatchQueue.main.async(execute: {
                        
                        AWLoader.hide()
                        
                    })
                    
                }
                
                
                
            }
            
        } catch {
            AWLoader.hide()
            print(error)
            
        }
    }
    
    task.resume()

Thanks for ideas.

starball
  • 20,030
  • 7
  • 43
  • 238
SwiftDeveloper
  • 7,244
  • 14
  • 56
  • 85
  • 2
    I was getting the same error because I was passing a string to the `dataTask(with:` e.g. I had `url = "www.yahoo.com` and I was passing it straight into the function **without** converting it to a `URL` – mfaani Jul 14 '17 at 15:49

14 Answers14

314

The compiler is confused by the function signature. You can fix it like this:

let task = URLSession.shared.dataTask(with: request as URLRequest) {

But, note that we don't have to cast "request" as URLRequest in this signature if it was declared earlier as URLRequest instead of NSMutableURLRequest:

var request = URLRequest(url:myUrl!)

This is the automatic casting between NSMutableURLRequest and the new URLRequest that is failing and which forced us to do this casting here.

Durul Dalkanat
  • 7,266
  • 4
  • 35
  • 36
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • 7
    `var request = URLRequest(url:myUrl!)` – Leo Dabus Jun 15 '16 at 01:03
  • 1
    [SE-0072](https://github.com/apple/swift-evolution/blob/master/proposals/0072-eliminate-implicit-bridging-conversions.md) said, remove implicit bridging. when "swifty function name" become "de facto override method", we can't reverse lookup Objective-C SEL,so we must use or cast to Foundation struct. – quesera2 Jun 15 '16 at 02:31
  • 2
    Very helpful answer. I'd only add that it would be good to avoid the myUrl! forced unwrapping by doing this: guard let myUrl = URL(string:listUrlString) else { return } then the request can be called without the ! var request = URLRequest(url:myUrl) – Mark Semsel Jul 27 '16 at 20:20
  • 2
    Can the `URL(string:)` constructor ever fail? – BallpointBen Feb 20 '17 at 20:38
  • Gotta vote up but I still have problem, it outputs "invalid value around character 0" anyone does? – Marfin. F Oct 08 '18 at 04:52
32

You have init'd myRequest as NSMutableURLRequest, you need this:

var URLRequest

Swift is ditching both the NSMutable... thing. Just use var for the new classes.

HenryRootTwo
  • 2,572
  • 1
  • 27
  • 27
17

Xcode 8 and Swift 3.0

Using URLSession:

 let url = URL(string:"Download URL")!
 let req = NSMutableURLRequest(url:url)
 let config = URLSessionConfiguration.default
 let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

 let task : URLSessionDownloadTask = session.downloadTask(with: req as URLRequest)
task.resume()

URLSession Delegate call:

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {

}


func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, 
didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
                   print("downloaded \(100*writ/exp)" as AnyObject)

}

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL){

}

Using Block GET/POST/PUT/DELETE:

 let request = NSMutableURLRequest(url: URL(string: "Your API URL here" ,param: param))!,
        cachePolicy: .useProtocolCachePolicy,
        timeoutInterval:"Your request timeout time in Seconds")
    request.httpMethod = "GET"
    request.allHTTPHeaderFields = headers as? [String : String] 

    let session = URLSession.shared

    let dataTask = session.dataTask(with: request as URLRequest) {data,response,error in
        let httpResponse = response as? HTTPURLResponse

        if (error != nil) {
         print(error)
         } else {
         print(httpResponse)
         }

        DispatchQueue.main.async {
           //Update your UI here
        }

    }
    dataTask.resume()

Working fine for me.. try it 100% result guarantee

Saumil Shah
  • 2,299
  • 1
  • 22
  • 27
15

This problem is caused by URLSession has two dataTask methods

open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask
open func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Swift.Void) -> URLSessionDataTask

The first one has URLRequest as parameter, and the second one has URL as parameter, so we need to specify which type to call, for example, I want to call the second method

let task = URLSession.shared.dataTask(with: url! as URL) {
    data, response, error in
    // Handler
}
mfaani
  • 33,269
  • 19
  • 164
  • 293
liwp_Stephen
  • 2,720
  • 1
  • 16
  • 11
10

In my case error was in NSURL

let url = NSURL(string: urlString)

In Swift 3 you must write just URL:

let url = URL(string: urlString)
Janserik
  • 2,306
  • 1
  • 24
  • 43
3

Tested xcode 8 stable version ; Need to use var request variable with URLRequest() With thats you can easily fix that (bug)

var request = URLRequest(url:myUrl!) And

let task = URLSession.shared().dataTask(with: request as URLRequest) { }

Worked fine ! Thank you guys, i think help many people. !

SwiftDeveloper
  • 7,244
  • 14
  • 56
  • 85
3

For Swift 3 and Xcode 8:

      var dataTask: URLSessionDataTask?

      if  let url = URL(string: urlString) {
            self.dataTask = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

                if let error = error {
                    print(error.localizedDescription)
                } else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
                     // You can use data received.
                    self.process(data: data as Data?)
                }
            })
        }
     }

//Note: You can always use debugger to check error

Naren
  • 1,504
  • 16
  • 19
3

In swift 3 the compiler is confused by the function signature. Specifying it will clear the error. Also convert the url string to type URL. The following code worked for me.

   let urlString = "http://bla.com?batchSize="
   let pathURL = URL(string: urlString)!
   var urlRequest = URLRequest(url:pathURL)

    let session = URLSession.shared
    let dataTask = session.dataTask(with: urlRequest as URLRequest) { (data,response,error) in
Alisha G
  • 41
  • 2
3

Short and concise answer for Swift 3:

guard let requestUrl = URL(string: yourURL) else { return }

let request = URLRequest(url:requestUrl)
URLSession.shared.dataTask(with: request) {
    (data, response, error) in
    ...

}.resume()
Josh
  • 529
  • 6
  • 21
2
 // prepare json data
        let mapDict = [ "1":"First", "2":"Second"]

        let json = [ "title":"ABC" , "dict": mapDict ] as [String : Any]
        let jsonData : NSData = NSKeyedArchiver.archivedData(withRootObject: json) as NSData

        // create post request
        let url = NSURL(string: "http://httpbin.org/post")!
        let request = NSMutableURLRequest(url: url as URL)
        request.httpMethod = "POST"

        // insert json data to the request
        request.httpBody = jsonData as Data


        let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
            if error != nil{
                return
            }
            do {
                let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject]

                print("Result",result!)

            } catch {
                print("Error -> \(error)")
            }
        }

        task.resume()
Nikunj Patel
  • 304
  • 2
  • 7
2

To load data via a GET request you don't need any URLRequest (and no semicolons)

let listUrlString =  "http://bla.com?batchSize=" + String(batchSize) + "&fromIndex=" + String(fromIndex)
let myUrl = URL(string: listUrlString)!
let task = URLSession.shared.dataTask(with: myUrl) { ...
vadian
  • 274,689
  • 30
  • 353
  • 361
2
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { data,response,error in
        if error != nil{
            print(error!.localizedDescription)
            return
        }
        if let responseJSON = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? [String:AnyObject]{
            if let response_token:String = responseJSON["token"] as? String {
                print("Singleton Firebase Token : \(response_token)")
                completion(response_token)
            }
        }
    })
    task.resume()
Imtee
  • 1,345
  • 13
  • 14
2

Xcode 10.1 Swift 4

This worked for me:

let task: URLSessionDataTask = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
...

The key was adding in the URLSessionDataTask type declaration.

Lane Faison
  • 278
  • 4
  • 7
1

For me I do this to find,

let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { (data, response, error) in ...}

Can't use

"let url = NSURL(string: urlString)
Rav
  • 1,327
  • 3
  • 18
  • 32