Skip to content

Instantly share code, notes, and snippets.

@Archetapp
Created October 16, 2020 00:14
Show Gist options
  • Select an option

  • Save Archetapp/f572c22b3b80a57a01236e31eff1c124 to your computer and use it in GitHub Desktop.

Select an option

Save Archetapp/f572c22b3b80a57a01236e31eff1c124 to your computer and use it in GitHub Desktop.
Network Speed Tester
//
// NetworkSpeedManager.swift
// Archetapp
//
// Created by Jared on 10/15/20.
// Copyright © 2020 Archetapp. All rights reserved.
//
import Foundation
import UIKit
public enum NetworkStatus : String
{case poor; case good; case disConnected}
class NetworkSpeedManager : NSObject, URLSessionDataDelegate, URLSessionDelegate {
@Published var speedStatus : NetworkStatus = .good
var startTime = CFAbsoluteTime()
var stopTime = CFAbsoluteTime()
var bytesReceived: CGFloat = 0
var speedTestCompletionHandler: ((_ megabytesPerSecond: CGFloat, _ error: Error?) -> Void)? = nil
var timerForSpeedTest:Timer?
var speedTestURL = "https://www.google.com"
func networkSpeedTestStart(){
timerForSpeedTest = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(testForSpeed), userInfo: nil, repeats: true)
}
func networkSpeedTestStop(){
timerForSpeedTest?.invalidate()
}
@objc func testForSpeed()
{
testDownloadSpeed(withTimout: 2.0, completionHandler: {(_ megabytesPerSecond: CGFloat, _ error: Error?) -> Void in
print("%0.1f; KbPerSec = \(megabytesPerSecond)")
if (error as NSError?)?.code == -1009
{
self.speedStatus = .disConnected
}
else if megabytesPerSecond == -1.0
{
self.speedStatus = .poor
}
else
{
self.speedStatus = .good
}
print(self.speedStatus.rawValue)
})
}
func testDownloadSpeed(withTimout timeout: TimeInterval, completionHandler: @escaping (_ megabytesPerSecond: CGFloat, _ error: Error?) -> Void) {
// you set any relevant string with any file
let urlForSpeedTest = URL(string: speedTestURL)
startTime = CFAbsoluteTimeGetCurrent()
stopTime = startTime
bytesReceived = 0
speedTestCompletionHandler = completionHandler
let configuration = URLSessionConfiguration.ephemeral
configuration.timeoutIntervalForResource = timeout
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
guard let checkedUrl = urlForSpeedTest else { return }
session.dataTask(with: checkedUrl).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
bytesReceived += CGFloat(data.count)
stopTime = CFAbsoluteTimeGetCurrent()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
let elapsed = (stopTime - startTime) //as? CFAbsoluteTime
let speed: CGFloat = elapsed != 0 ? bytesReceived / (CGFloat(CFAbsoluteTimeGetCurrent() - startTime)) / 1024.0 : -1.0
// treat timeout as no error (as we're testing speed, not worried about whether we got entire resource or not
if error == nil || ((((error as NSError?)?.domain) == NSURLErrorDomain) && (error as NSError?)?.code == NSURLErrorTimedOut) {
speedTestCompletionHandler?(speed, nil)
}
else {
speedTestCompletionHandler?(speed, error)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment