Swift 3 URLSession.shared () 멤버 'dataTask (with : completionHandler :)에 대한 모호한 참조 오류 (버그)


169

안녕하세요, swift2.2에 대한 JSON 구문 분석 코드를 작업하고 있지만 Swift 3.0에 사용할 때 오류가 발생합니다.

ViewController.swift : 132 : 31 : 'dataTask (with : completionHandler :)'멤버에 대한 모호한 참조

내 코드는 여기

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

아이디어 주셔서 감사합니다.


2
내가 가진 dataTask(with:예에 문자열을 전달했기 때문에 같은 오류가 발생 url = "www.yahoo.com했습니다. 그리고 그것을 문자열로 변환 하지 않고 함수로 직접 전달했습니다URL
Honey

답변:


312

함수 서명으로 인해 컴파일러가 혼동됩니다. 다음과 같이 고칠 수 있습니다.

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

그러나, 우리가로 캐스트 "요청"을 필요는 없습니다 URLRequest이 서명의 경우 가 이전과 같이 선언 URLRequest대신 NSMutableURLRequest:

var request = URLRequest(url:myUrl!)

이것은 실패한 NSMutableURLRequest새로운 URLRequest것 사이의 자동 캐스팅 이며 여기서 우리는이 캐스팅을 수행해야합니다.


7
var request = URLRequest(url:myUrl!)
Leo Dabus 2016 년

1
SE-0072 는 암묵적 브리징을 제거한다고 말했다. "swifty function name"이 "실제 재정의 방법"이되면 Objective-C SEL 조회를 되돌릴 수 없으므로 Foundation 구조체를 사용하거나 캐스트해야합니다.
quesera2

2
매우 유용한 답변. 나는 myUrl을 피하는 것이 좋을 것이라고 덧붙였다. 다음과 같이 강제로 래핑 해제 : guard let myUrl = URL (string : listUrlString) else {return} 그러면!없이 요청을 호출 할 수 있습니다. var request = URLRequest (url : myUrl)
Mark Semsel

2
URL(string:)생성자는 지금까지 실패?
BallpointBen

투표해야하는데 여전히 문제가 있습니다. "문자 0 주위의 유효하지 않은 값"을 출력합니까?
마핀. F

33

당신은 다음 myRequest과 같이 초기화 했습니다 NSMutableURLRequest.

var URLRequest

스위프트는 둘 다 버리고 있습니다 NSMutable.... 그냥 사용하는 var새로운 클래스.


17

Xcode 8 및 Swift 3.0

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 대리인 전화 :

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

}

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

나를 위해 잘 작동합니다. 100 % 결과 보장


15

이 문제는 URLSession에 두 개의 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

첫 번째는 URLRequest매개 변수로 사용하고 두 번째는 URL매개 변수로 사용하므로 호출 할 유형을 지정해야합니다. 예를 들어 두 번째 방법을 호출하고 싶습니다.

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

이해가되었습니다. 감사합니다
iBug

10

내 경우에는 NSURL에 오류가있었습니다.

let url = NSURL(string: urlString)

Swift 3에서는 URL 만 작성해야합니다 .

let url = URL(string: urlString)

3

테스트 된 xcode 8 안정 버전; var requestURLRequest()함께 변수 를 사용해야 합니다. 그것으로 쉽게 고칠 수 있습니다 ( 버그 )

var request = URLRequest(url:myUrl!)

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

잘 작동했습니다! 고맙습니다. 많은 사람들을 도와주세요. !


1
이렇게 된 URLRequest에서하는 URLRequest에 캐스트에 이해되지 않는다
레오 버스들이시길에게

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

sharedSwift 3의 함수가 아닌 속성입니다 (괄호 없음).
vadian

@vadian 내가 의견을 게시 할 당시가 아닙니다
Leo Dabus

3

스위프트 3 및 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?)
                }
            })
        }
     }

// 참고 : 언제든지 디버거를 사용하여 오류를 확인할 수 있습니다


3

신속한 3에서 컴파일러는 함수 서명에 의해 혼동됩니다. 지정하면 오류가 지워집니다. URL 문자열을 URL 유형으로 변환하십시오. 다음 코드는 저에게 효과적이었습니다.

   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

스위프트 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

GET 요청을 통해 데이터를로드하려면 URLRequest세미콜론이 필요하지 않습니다.

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 스위프트 4

이것은 나를 위해 일했다 :

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

열쇠는 URLSessionDataTask형식 선언을 추가하는 것이 었습니다 .


1

나를 위해 나는 이것을 찾기 위해,

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

사용할 수 없습니다

"let url = NSURL(string: urlString)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.