Swift 3 URLSession.shared () Referencia ambigua a la dataTask del miembro (con: completeHandler :) error (error)


169

Hola, tengo un código de análisis json que funciona para swift2.2 pero cuando lo uso para Swift 3.0 me da ese error

ViewController.swift: 132: 31: referencia ambigua al miembro 'dataTask (con: completeHandler :)'

Mis codigos aqui

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

Gracias por las ideas


2
Estaba recibiendo el mismo error porque estaba pasando una cadena a la dataTask(with:que tenía, por ejemplo, url = "www.yahoo.comy la estaba pasando directamente a la función sin convertirla en unURL
Honey

Respuestas:


312

El compilador está confundido por la firma de la función. Puedes arreglarlo así:

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

Pero, tenga en cuenta que no tenemos que emitir "solicitud" como URLRequesten esta firma si se declaró antes como en URLRequestlugar de NSMutableURLRequest:

var request = URLRequest(url:myUrl!)

Este es el casting automático entre NSMutableURLRequesty lo nuevo URLRequestque está fallando y que nos obligó a hacer este casting aquí.


77
var request = URLRequest(url:myUrl!)
Leo Dabus

1
SE-0072 dijo, eliminar el puente implícito. cuando "nombre de función rápido" se convierte en "método de anulación de facto", no podemos revertir la búsqueda de Objective-C SEL, por lo que debemos usar o convertir a Foundation struct.
quesera2

2
Muy útil respuesta. ¡Solo agregaría que sería bueno evitar myUrl! desenvolvimiento forzado al hacer esto: guard let myUrl = URL (string: listUrlString) else {return} entonces la solicitud puede ser llamada sin el! var request = URLRequest (url: myUrl)
Mark Semsel

2
¿Puede el URL(string:)constructor fallar alguna vez?
BallpointBen

Tengo que votar pero todavía tengo un problema, ¿muestra "valor no válido alrededor del carácter 0" que alguien hace?
Marfin. F

33

Has iniciado myRequestcomo NSMutableURLRequest, necesitas esto:

var URLRequest

Swift está abandonando tanto la NSMutable...cosa. Solo úsalo varpara las nuevas clases.


17

Xcode 8 y Swift 3.0

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

Llamada de delegado de URLSession:

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

}

Usando el bloque 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()

Funciona bien para mí ... pruébalo 100% de garantía de resultados


15

Este problema es causado por URLSession tiene dos métodos dataTask

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

El primero tiene URLRequestcomo parámetro, y el segundo tiene URLcomo parámetro, por lo que debemos especificar a qué tipo llamar, por ejemplo, quiero llamar al segundo método

let task = URLSession.shared.dataTask(with: url! as URL) {
    data, response, error in
    // Handler
}

Tenía sentido. Gracias
iBug el

10

En mi caso el error estaba en NSURL

let url = NSURL(string: urlString)

En Swift 3 debe escribir solo la URL :

let url = URL(string: urlString)

3

Versión estable probada de xcode 8; Necesitas usar var requestvariables con URLRequest()With eso puedes arreglarlo fácilmente ( error )

var request = URLRequest(url:myUrl!) Y

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

Funcionó bien! Gracias chicos, creo que ayuda a mucha gente. !


1
Esto no tiene sentido transmitir de URLRequest a URLRequest
Leo Dabus

var request = URLRequest(url: url); let task = URLSession.shared().dataTask(with: request) { ... }
Leo Dabus

sharedes una propiedad en lugar de una función en Swift 3 (sin paréntesis).
vadian 01 de

@vadian no en el momento en que publiqué el comentario
Leo Dabus el

3

Para Swift 3 y 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?)
                }
            })
        }
     }

// Nota: siempre puede usar el depurador para verificar el error


3

En swift 3, el compilador se confunde con la firma de la función. Al especificarlo se borrará el error. También convierta la cadena de url para escribir URL. El siguiente código funcionó para mí.

   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

3

Respuesta breve y concisa para 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()

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

2

Para cargar datos a través de una solicitud GET, no necesita ninguno URLRequest(ni punto y coma)

let listUrlString =  "http://bla.com?batchSize=" + String(batchSize) + "&fromIndex=" + String(fromIndex)
let myUrl = URL(string: listUrlString)!
let task = URLSession.shared.dataTask(with: myUrl) { ...

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

2

Xcode 10.1 Swift 4

Esto funcionó para mí:

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

La clave fue agregar en la URLSessionDataTaskdeclaración de tipo.


1

Para mí hago esto para encontrar,

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

No puede usar

"let url = NSURL(string: urlString)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.