Swift 3, URLSession dataTask completionHandler not called

六眼飞鱼酱① 提交于 2019-11-30 09:59:01

I made a simple App from scratch. (Xcode 8 beta 6 / swift 3) In controller I pasted Your code. (plus url creation..) I see all in debugger:

THIS ONE IS PRINTED

THIS ONE IS PRINTED, TOO

I AM BACK

so it seems workin.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let URLString = "https://apple.com"
        let url = URL(string: URLString)
        let request = URLRequest(url: url!)


        ViewController.execTask(request: request) { (ok, obj) in

            print("I AM BACK")

        }

    }

    private class func execTask(request: URLRequest, taskCallback: @escaping (Bool,
        AnyObject?) -> ()) {

        let session = URLSession(configuration: URLSessionConfiguration.default)
        print("THIS LINE IS PRINTED")
        let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
            if let data = data {
                print("THIS ONE IS PRINTED, TOO")
                let json = try? JSONSerialization.jsonObject(with: data, options: [])
                if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
                    taskCallback(true, json as AnyObject?)
                } else {
                    taskCallback(false, json as AnyObject?)
                }
            }
        })
        task.resume()
    }

}
xrage

Did the changes suggested here, It works now.

Using NSURLSession from a Swift command line program

var sema = DispatchSemaphore( value: 0 )

private func execTask(request: URLRequest, taskCallback: @escaping (Bool,
    AnyObject?) -> ()) {

    let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil )

    session.dataTask(with: request) {(data, response, error) -> Void in
        if let data = data {
            let json = try? JSONSerialization.jsonObject(with: data, options: [])
            if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
                taskCallback(true, json as AnyObject?)
            } else {
                taskCallback(false, json as AnyObject?)
            }
        }
    }.resume()
    sema.wait()
}
Ankit

I know its late for the answer but in case you have not figure out the issue or getting issue at other places, lets try this.

You need to save session variable outside method scope (make it a instance variable). Since you defined it locally in function scope. Its get deallocated before completion handler can be called, remember completion handler can't retain your session object and after execution of run loop, garbage collector will dealloc your session object. We need to retain such objects whenever we want call back from delegates or from completion handler..

self.session = URLSession(configuration: URLSessionConfiguration.default)
JKLTechnologies
let dataTask = session.dataTask(with: request, completionHandler: {data, response,error -> Void in 
    print("Request : \(response)")

    let res = response as! HTTPURLResponse

    print("Status Code : \(res.statusCode)")

    let strResponse = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
    print("Response String :\(strResponse)")
    })
dataTask.resume()

Swift 3.0

Just copy below code into your view controller.

@IBAction func btnNewApplicationPressed (_ sender: UIButton) {
        callWebService()
}

func callWebService() {
    // Show MBProgressHUD Here
    var config                              :URLSessionConfiguration!
    var urlSession                          :URLSession!

    config = URLSessionConfiguration.default
    urlSession = URLSession(configuration: config)

    // MARK:- HeaderField
    let HTTPHeaderField_ContentType         = "Content-Type"

    // MARK:- ContentType
    let ContentType_ApplicationJson         = "application/json"

    //MARK: HTTPMethod
    let HTTPMethod_Get                      = "GET"

    let callURL = URL.init(string: "https://itunes.apple.com/in/rss/newapplications/limit=10/json")

    var request = URLRequest.init(url: callURL!)

    request.timeoutInterval = 60.0 // TimeoutInterval in Second
    request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
    request.addValue(ContentType_ApplicationJson, forHTTPHeaderField: HTTPHeaderField_ContentType)
    request.httpMethod = HTTPMethod_Get

    let dataTask = urlSession.dataTask(with: request) { (data,response,error) in
        if error != nil{
            return
        }
        do {
            let resultJson = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject]
            print("Result",resultJson!)
        } catch {
            print("Error -> \(error)")
        }
    }

    dataTask.resume()
}

Sometimes, for me, the solution when completionHandler were not called in these cases was because the flag "Allow Arbitrary loads" on Info.plist was defined as NO.

Allow Arbitrary loads flag defined as YES

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!