我们如何检查 iOS Swift 中连接的网络连接是否可达?

How can we check whether connected network connection is reachable or not in iOS Swift?

我的应用程序支持 iOS12 或更高版本,我使用的是最新的 macOS 和 xcode。我对这个主题进行了多项研究,但找不到任何合适的解决方案。是的,我知道如何检查我们是否已连接到网络并且也可以获取连接类型。但问题是:我连接的网络是否可达?我正在与物联网设备通信,我必须从中获取一些数据,并将其发送到不同的服务器。该设备总是给我数据,因为它是一个内部网,因为我连接到它的热点。我必须检查它是否可以自己将数据进一步发送到另一个远程服务器(有时网络连接不起作用),或者如果不能,我需要将 wifi 连接切换到我的本地网络。试了好几种方法都没有得到满意的结果

最佳做法是尝试:调用网络请求并检查结果。如果出现错误,您该怎么办取决于您的用例、是否涉及用户或是否在后台发出请求。

例如,您可能只输出一个错误,让用户在应用中继续操作。这可能需要相应地设计您的屏幕,即提供一种用户可以重试的方式(在您显示内容的屏幕中,显示一个空的内容屏幕并提供下拉刷新或“重试”按钮等.).

或者,您可以分析错误的种类(URL 错误或响应错误)并可以应用多种策略。例如,如果网络请求可以在后台执行,您可以在获得 5xx HTTP 状态时应用重试。或者,如果连接丢失(无响应并且您收到 URL 错误),您可能会开始观察网络状态并在网络可用时重试。

上面@Joakim Danielson说的就是你应该做的。无论您使用什么来源,它总会在某些时候为您提供虚假信息(关于是否连接到互联网)。

  1. 拨打 api 电话。
  2. 检查错误 - 是否是临时网络错误?
  3. 决定是否应该重试或向用户显示其他内容。

如何检查是否可能是暂时的网络错误?

您可以在从 api 调用返回的 NSError 实例上使用此扩展。

public extension NSError {
    
    var isConnectionAborted: Bool {
        return (self.domain == NSPOSIXErrorDomain && self.code == 53)
    }
    
    var isTemporaryNetworkError: Bool {
        let temporaryNetworkErrorCodes = [
            NSURLErrorTimedOut,
            NSURLErrorCannotFindHost,
            NSURLErrorCannotConnectToHost,
            NSURLErrorNetworkConnectionLost,
            NSURLErrorDNSLookupFailed,
            NSURLErrorHTTPTooManyRedirects,
            NSURLErrorResourceUnavailable,
            NSURLErrorNotConnectedToInternet,
            NSURLErrorRedirectToNonExistentLocation,
            NSURLErrorSecureConnectionFailed,
            NSURLErrorCannotLoadFromNetwork,
            NSURLErrorRequestBodyStreamExhausted,
        ]
        
        return (self.isConnectionAborted || temporaryNetworkErrorCodes.contains(self.code))
    }
    
    var isCancelled: Bool {
        return (self.domain == NSURLErrorDomain && self.code == NSURLErrorCancelled)
    }

}

我尝试了一个api呼叫,它失败了,现在我想查询我是否连接到互联网。怎么知道?

在您的 API 代码中的某处,您可以使用 NWPathMonitor 添加观察者以观察可能的网络变化 - 需要 iOS 12

import Network

let monitor = NWPathMonitor()
monitor.start(queue: DispatchQueue(label: "NetworkMonitor"))
monitor.pathUpdateHandler = { (path) in
    if path.status == .satisfied {
        print("Connected")
    } else {
        print("Not Connected")
    }
}

这也允许更精细的控制 .cellular.wifi.wiredEthernet 等。-

let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)

如果您仍然支持 iOS 11,您可以使用第 3 方库,例如 - Reachability