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)
}
}
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, 2022Comments
-
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!