Right way of determining internet speed in iOS 8

13,042

Solution 1

You code snippet was taken from this answer. I've updated it to use NSURLSession. The Swift rendition is below:

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

}

Solution 2

Here is the updated code in Swift 4.0

class SpeedTest: UIViewController, URLSessionDelegate, URLSessionDataDelegate {


    typealias speedTestCompletionHandler = (_ megabytesPerSecond: Double? , _ error: Error?) -> Void

    var speedTestCompletionBlock : speedTestCompletionHandler?

    var startTime: CFAbsoluteTime!
    var stopTime: CFAbsoluteTime!
    var bytesReceived: Int!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        checkForSpeedTest()

    }

    func checkForSpeedTest() {

        testDownloadSpeedWithTimout(timeout: 5.0) { (speed, error) in
            print("Download Speed:", speed ?? "NA")
            print("Speed Test Error:", error ?? "NA")
        }

    }

    func testDownloadSpeedWithTimout(timeout: TimeInterval, withCompletionBlock: @escaping speedTestCompletionHandler) {

        guard let url = URL(string: "https://images.apple.com/v/imac-with-retina/a/images/overview/5k_image.jpg") else { return }

        startTime = CFAbsoluteTimeGetCurrent()
        stopTime = startTime
        bytesReceived = 0

        speedTestCompletionBlock = withCompletionBlock

        let configuration = URLSessionConfiguration.ephemeral
        configuration.timeoutIntervalForResource = timeout
        let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: nil)
        session.dataTask(with: url).resume()

    }

    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

        if let aTempError = error as NSError?, aTempError.domain != NSURLErrorDomain && aTempError.code != NSURLErrorTimedOut && elapsed == 0  {
            speedTestCompletionBlock?(nil, error)
            return
        }

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

    }

}
Share:
13,042
Saty
Author by

Saty

HI All, I am a iphone Developer and Android Developer having almost 5 Years of experience in building Mobile Application.

Updated on June 14, 2022

Comments

  • Saty
    Saty almost 2 years

    I am following the below code which I copied and converted from a stack overflow question.

    I am getting internet speed however I am not sure, If I am doing right thing.

    import UIKit
    
    class ViewController: UIViewController, NSURLConnectionDataDelegate{
    var connection:NSURLConnection!
    var length:Int!
    var startTime:NSDate!
    
    //let kMinimumMegabytesPerSecond: CGFloat = 1
    
    let kMaximumElapsedTime: CGFloat = 2.0
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.testDownloadSpeed()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    func testDownloadSpeed() {
        var url: NSURL = NSURL(string: "http://thewallpaperhost.com/wp-content/uploads/2014/12/wallpapers-hd-8000-8331-hd-wallpapers.jpg")!
        var request: NSURLRequest = NSURLRequest(URL: url)
        self.startTime = NSDate()
        self.length = 0
        self.connection = NSURLConnection(request: request, delegate: self)
        self.connection.start()
        let delayInSeconds:Int64 =  1000000000  * 2
        var popTime:dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, (Int64)(delayInSeconds ))
        dispatch_after(popTime, dispatch_get_main_queue(), {() -> Void in
           if let conn = self.connection {
                self.connection.cancel()
                self.connection = nil
                self.useOffline()
            }
        })
    }
    
    func determineMegabytesPerSecond() -> CGFloat {
        var elapsed: NSTimeInterval
        if (startTime != nil) {
            elapsed = NSDate().timeIntervalSinceDate(startTime)
            var d =  (Double(length) / elapsed)
            var result = CGFloat( d/1024)
            result = result * 0.0078125
            result = result * 0.0009765625
            return result
    
        }
        return -1
    }
    
    func useOnline() {
         NSLog("Successful")
         NSLog("\(determineMegabytesPerSecond())")
    
    }
    
    func useOffline() {
    
        NSLog("UnSuccessful")
        NSLog("\(determineMegabytesPerSecond())")
    }
    
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        NSLog("data came")
        self.startTime = NSDate()
    }
    
    
    func connection(connection: NSURLConnection, didFailWithError error: NSError) {
        if let conn = self.connection {
            self.connection = nil
            useOffline()
        }
    }
    
    
    func connectionDidFinishLoading(connection: NSURLConnection) {
        self.connection = nil
    
        useOnline()
    }
    
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
        self.length  = self.length +  data.length
        NSLog("\(data.length)")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    }
    

    I copied the code from below URL. It was in Objective C so I converted the code!

    How to detect Network Signal Strength in iOS Reachability