1

I want to use the code answer of this question because it's exactly what I'm looking for. But I can't use something that I don't really understand.

Can anyone please explain to me how this code calculate the download speed?

class ViewController: UIViewController, NSURLSessionDelegate, NSURLSessionDataDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        testDownloadSpeedWithTimout(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: NSTimeInterval, completionHandler:(megabytesPerSecond: Double?, error: NSError?) -> ()) {
        let url = NSURL(string: "http://insert.your.site.here/yourfile")!

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

        let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
        configuration.timeoutIntervalForResource = timeout
        let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
        session.dataTaskWithURL(url).resume()
    }

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

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

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

}
Community
  • 1
  • 1
Ne AS
  • 1,490
  • 3
  • 26
  • 58

1 Answers1

0

The bottom function is a delegate callback for when the URLSession finishes the download. The speed calculation is done on the second last line of this function:

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

This is saying if elapsed time isn't 0 take the total amount of bytes received and divide by the amount of seconds elapsed (this is calculated by taking the start time subtracted by the time when the session: dataTask: didReceiveData: delegate method above is called).Then divide by 1024.0 twice to go from bytes -> megabytes. Otherwise, it returns -1.

psobko
  • 1,548
  • 1
  • 14
  • 24