如何在 swift 中检查设备的互联网连接是否不良

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

我想检查设备的互联网连接速度是否很慢。

我已经使用 Reachability class 检查互联网连接是否可用。

但是我想每隔几秒检查一次网速是否不差。

这是否可能找到,是的,我该怎么做。

您可以使用下面给出的方法在固定时间间隔后每次调用 Reachability class:

override func viewDidLoad() {               
       scheduledTimerWithTimeInterval()
   }
   func scheduledTimerWithTimeInterval(){
       // Scheduling timer to Call the function "updateCounting" with the interval of 'x' seconds 
       timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateCounting), userInfo: nil, repeats: true)
   }

@objc func updateCounting(){
       \Do your stuff here(Check Reachabilty Here)
   }

编辑: 这是检查蜂窝网络信号强度的方法。

func getSignalStrength() -> Int {

let application = UIApplication.shared
let statusBarView = application.value(forKey: "statusBar") as! UIView
let foregroundView = statusBarView.value(forKey: "foregroundView") as! UIView
let foregroundViewSubviews = foregroundView.subviews

var dataNetworkItemView:UIView? = nil

for subview in foregroundViewSubviews {

    if subview.isKind(of: NSClassFromString("UIStatusBarSignalStrengthItemView")!) {
        dataNetworkItemView = subview
        break
    }
}

 if dataNetworkItemView == nil
 {
    return 0
 }
return dataNetworkItemView?.value(forKey: "signalStrengthBars") as! Int

} 

对于 Wifi 网络,这是获取信号强度的方法

private func getWiFiRSSI() -> Int? {
    let app = UIApplication.shared
    var rssi: Int?
    let exception = tryBlock {
        guard let statusBar = app.value(forKey: "statusBar") as? UIView else { return }
        if let statusBarMorden = NSClassFromString("UIStatusBar_Modern"), statusBar .isKind(of: statusBarMorden) { return }

        guard let foregroundView = statusBar.value(forKey: "foregroundView") as? UIView else { return  }

        for view in foregroundView.subviews {
            if let statusBarDataNetworkItemView = NSClassFromString("UIStatusBarDataNetworkItemView"), view .isKind(of: statusBarDataNetworkItemView) {
                if let val = view.value(forKey: "wifiStrengthRaw") as? Int {
                    rssi = val
                    break
                }
            }
        }
    }
    if let exception = exception {
        print("getWiFiRSSI exception: \(exception)")
    }
    return rssi
}

编辑 2: 添加此扩展以访问您的状态栏视图

extension UIApplication {
    var statusBarUIView: UIView? {
        if #available(iOS 13.0, *) {
            let tag = 38482458385
            if let statusBar = self.keyWindow?.viewWithTag(tag) {
                return statusBar
            } else {
                let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
                statusBarView.tag = tag

                self.keyWindow?.addSubview(statusBarView)
                return statusBarView
            }
        } else {
            if responds(to: Selector(("statusBar"))) {
                return value(forKey: "statusBar") as? UIView
            }
        }
        return nil
    }
}

我已经创建了解决方案并将其添加到这里。

只需创建 class 并将其粘贴并在您需要的地方使用。

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

之后如何使用 it.So 实现委托并使用它。

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