Swift 3 URLSession.shared () การอ้างอิงที่คลุมเครือกับ dataTask ของสมาชิก (พร้อมกับ: completionHandler :) error (ข้อผิดพลาด)


169

สวัสดีฉันใช้ json ในการแยกวิเคราะห์รหัสสำหรับ swift2.2 แต่เมื่อฉันใช้กับ Swift 3.0 จะทำให้ฉันมีข้อผิดพลาด

ViewController.swift: 132: 31: การอ้างอิงที่คลุมเครือกับ dataTask ของสมาชิก (ด้วย: 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และฉันส่งมันโดยตรงไปยังฟังก์ชันโดยไม่แปลงเป็น aURL
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

1
SE-0072กล่าวว่าให้ลบการเชื่อมโยงโดยนัย เมื่อ "ชื่อฟังก์ชั่น swifty" กลายเป็น "วิธีการแทนที่โดยพฤตินัย" เราไม่สามารถย้อนกลับการค้นหา Objective-C SEL ได้ดังนั้นเราจึงต้องใช้หรือส่งไปยังโครงสร้างของมูลนิธิ
quesera2

2
คำตอบที่เป็นประโยชน์มาก ฉันแค่เพิ่มว่ามันจะดีเพื่อหลีกเลี่ยง myUrl! บังคับให้คลายออกโดยทำสิ่งนี้: Guard ให้ myUrl = URL (string: listUrlString) อื่น {return} จากนั้นจะสามารถเรียกใช้คำร้องขอได้โดยไม่ต้องใช้! var request = URLRequest (url: myUrl)
ทำเครื่องหมาย 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){

}

ใช้ 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()

ทำงานได้ดีสำหรับฉัน .. ลองรับประกันผล 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 requestตัวแปรด้วยURLRequest()ด้วยคุณสามารถแก้ไขได้อย่างง่ายดาย ( ข้อผิดพลาด )

var request = URLRequest(url:myUrl!) และ

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

ทำงานได้ดี! ขอบคุณพวกคุณฉันคิดว่าช่วยคนจำนวนมาก !


1
วิธีนี้ไม่เหมาะสมที่จะส่งจาก URLRequest ไปยัง URLRequest
Leo Dabus

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

sharedเป็นคุณสมบัติแทนที่จะเป็นฟังก์ชันใน Swift 3 (ไม่มีวงเล็บ)
vadian

@vadian ไม่ได้ในเวลาที่ฉันโพสต์ความคิดเห็น
Leo Dabus

3

สำหรับ Swift 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

ใน swift 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

คำตอบที่สั้นและกระชับสำหรับ 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

ในการโหลดข้อมูลผ่านคำขอ 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 Swift 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.