Search code examples
iosswiftiphonereachability-swift

How to check if device is having poor internet connection in swift


I want to check if device is having very slow internet connection.

I have used Reachability class to check for internet connection is available or not.

But here i want to check after every few sec that internet speed is not poor.

Is this possible to find and yes than how can i do it.


Solution

  • I have founded solution and adding it here.

    Simply create class and paste it and use it where you want.

    protocol NetworkSpeedProviderDelegate: class {
        func callWhileSpeedChange(networkStatus: NetworkStatus)
       }
    public enum NetworkStatus :String
    {case poor; case good; case disConnected}
    
    class NetworkSpeedTest: UIViewController {
        
        weak var delegate: NetworkSpeedProviderDelegate?
        var startTime = CFAbsoluteTime()
        var stopTime = CFAbsoluteTime()
        var bytesReceived: CGFloat = 0
        var testURL:String?
        var speedTestCompletionHandler: ((_ megabytesPerSecond: CGFloat, _ error: Error?) -> Void)? = nil
        var timerForSpeedTest:Timer?
        
        func networkSpeedTestStart(UrlForTestSpeed:String!){
            testURL = UrlForTestSpeed
            timerForSpeedTest = Timer.scheduledTimer(timeInterval: 60.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.delegate?.callWhileSpeedChange(networkStatus: .disConnected)
                }
                else if megabytesPerSecond == -1.0
                {
                    self.delegate?.callWhileSpeedChange(networkStatus: .poor)
                }
                else
                {
                    self.delegate?.callWhileSpeedChange(networkStatus: .good)
                }
            })
        }
    }
    extension NetworkSpeedTest: URLSessionDataDelegate, URLSessionDelegate {
    
    func testDownloadSpeed(withTimout timeout: TimeInterval, completionHandler: @escaping (_ megabytesPerSecond: CGFloat, _ error: Error?) -> Void) {
    
        // you set any relevant string with any file
        let urlForSpeedTest = URL(string: testURL!)
    
        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)
        }
      }
    }
    

    After That how to use it.So implement delegate and use it.

    class ViewController: UIViewController, NetworkSpeedProviderDelegate {
        func callWhileSpeedChange(networkStatus: NetworkStatus) {
            switch networkStatus {
            case .poor:
                break
            case .good:
                break
            case .disConnected:
                break
            }
        }
        
        let test = NetworkSpeedTest()
        override func viewDidLoad() {
            super.viewDidLoad()
            test.delegate = self
            test.networkSpeedTestStop()
            test.networkSpeedTestStart(UrlForTestSpeed: "Paste Your Any Working URL ")
            // Do any additional setup after loading the view.
        }
    }