-1

I would like to see how long a download took, and I saw this link on how to do it , so I tweaked it a bit (e.g. changing renamed classes and so on) to work in Swift 3. However, I have one problem on the line: let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)that I just cannot fix, and this error message keeps popping up:

Argument labels '(configuration:, delegate:, delegateQueue:)' do not match any available overloads

Here is my code: (The problematic line is the one following // ISSUE ON NEXT LINE)

import UIKit

class ViewController: UIViewController, URLSessionDelegate, URLSessionDataDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    testDownloadSpeedWithTimout(timeout: 5.0) { (megabytesPerSecond, error) -> () in
        print("\(megabytesPerSecond); \(error)")
    }
}

var startTime: CFAbsoluteTime!
var stopTime: CFAbsoluteTime!
var bytesReceived: Int!
var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!

/// Test speed of download
///
/// Test the speed of a connection by downloading some predetermined resource. Alternatively, you could add the
/// URL of what to use for testing the connection as a parameter to this method.
///
/// - parameter timeout:             The maximum amount of time for the request.
/// - parameter completionHandler:   The block to be called when the request finishes (or times out).
///                                  The error parameter to this closure indicates whether there was an error downloading
///                                  the resource (other than timeout).
///
/// - note:                          Note, the timeout parameter doesn't have to be enough to download the entire
///                                  resource, but rather just sufficiently long enough to measure the speed of the download.

func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ()) {
    let url = NSURL(string: "http://insert.your.site.here/yourfile")!

    startTime = CFAbsoluteTimeGetCurrent()
    stopTime = startTime
    bytesReceived = 0
    speedTestCompletionHandler = completionHandler

    let configuration = URLSessionConfiguration.ephemeral
    configuration.timeoutIntervalForResource = timeout

    ////////////////// ISSUE ON NEXT LINE ///////////////////

    let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    session.dataTaskWithURL(url).resume()
}

func URLSession(session: URLSession, dataTask: URLSessionDataTask, didReceiveData data: NSData) {
    bytesReceived! += data.length
    stopTime = CFAbsoluteTimeGetCurrent()
}

func URLSession(session: URLSession, task: URLSessionTask, didCompleteWithError error: NSError?) {
    let elapsed = stopTime - startTime
    guard elapsed != 0 && (error == nil || (error?.domain == NSURLErrorDomain && error?.code == NSURLErrorTimedOut)) else {
        speedTestCompletionHandler?(nil, error)
        return
    }

    let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
    speedTestCompletionHandler?(speed, nil)
}

}

Could anyone kindly tell me what is the problem here? I've been stuck for quite a while now. Thanks!

Community
  • 1
  • 1
Tony Tarng
  • 699
  • 2
  • 8
  • 17

1 Answers1

0

check the corrected code below

import UIKit

/* check delegate changes */

class ViewController: UIViewController, URLSessionTaskDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        testDownloadSpeedWithTimout(timeout: 5.0) { (megabytesPerSecond, error) -> () in
            print("\(megabytesPerSecond); \(error)")
        }
    }

    var startTime: CFAbsoluteTime!
    var stopTime: CFAbsoluteTime!
    var bytesReceived: Int!
    var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!

    /// Test speed of download
    ///
    /// Test the speed of a connection by downloading some predetermined resource. Alternatively, you could add the
    /// URL of what to use for testing the connection as a parameter to this method.
    ///
    /// - parameter timeout:             The maximum amount of time for the request.
    /// - parameter completionHandler:   The block to be called when the request finishes (or times out).
    ///                                  The error parameter to this closure indicates whether there was an error downloading
    ///                                  the resource (other than timeout).
    ///
    /// - note:                          Note, the timeout parameter doesn't have to be enough to download the entire
    ///                                  resource, but rather just sufficiently long enough to measure the speed of the download.

    func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ()) {

        let url = URL(string: "http://insert.your.site.here/yourfile")!

        startTime = CFAbsoluteTimeGetCurrent()
        stopTime = startTime
        bytesReceived = 0
        speedTestCompletionHandler = completionHandler

        let configuration = URLSessionConfiguration.ephemeral
        configuration.timeoutIntervalForResource = timeout

        ////////////////// ISSUE ON NEXT LINE IS NOW RESOLVED///////////////////

        let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
        session.dataTask(with: url).resume()
    }

    /* changes is below */

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        bytesReceived! += data.count
        stopTime = CFAbsoluteTimeGetCurrent()
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        let elapsed = stopTime - startTime

        guard let nserror = error as? NSError, elapsed != 0 && (nserror.domain == NSURLErrorDomain && nserror.code == NSURLErrorTimedOut) else {
            speedTestCompletionHandler?(nil, error as? NSError)
            return
        }

        let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
        speedTestCompletionHandler?(speed, nil)
    }

   /* changes end */

}
Nikunj Damani
  • 753
  • 3
  • 11
  • @Tony Tarng have you checked the code and tried it ? – Nikunj Damani Feb 17 '17 at 07:00
  • Hi, I have just tried it, and I'm getting this error message: > 2017-02-17 15:21:10.242258 WiFi Testing[29684:8630707] [] __nw_connection_get_connected_socket_block_invoke 2 Connection has no connected handler 2017-02-17 15:21:10.287149 WiFi Testing[29684:8630710] [] __nw_connection_get_connected_socket_block_invoke 3 Connection has no connected handler 2017-02-17 15:21:10.289084 WiFi Testing[29684:8630729] PAC stream failed with 2017-02-17 15:21:10.291110 WiFi Testing[29684:8630710] [] nw_proxy_resolver_create_parsed_array PAC evaluation error: kCFErrorDomainCFNetwork: 2 nil; nil – Tony Tarng Feb 17 '17 at 07:22
  • Also, if it makes any difference, the download test source I'm using is: https://turnkeyinternet.net/speed-test/1mb.bin – Tony Tarng Feb 17 '17 at 07:24
  • here i have solved your error i.e. you are not able to create session instance. further i have not tested anything. – Nikunj Damani Feb 17 '17 at 07:29
  • Yes, there is no longer any error at compile time. But it sends the above message to console when launched. Do you have any idea why that is the case? (I'm using https links since http isn't allowed unless if you change info.plist) – Tony Tarng Feb 17 '17 at 07:43
  • then please can you accept this answer as your error is resolved ? – Nikunj Damani Feb 17 '17 at 08:31