使用可达性库到基于Swiftui的应用程序来通知网络丢失
我对使用 cocoapods 的 ios && 非常陌生。
我扫描了 SO 以找到检测网络状态的最简单方法,许多答案将我定向到 AshleyMills 的 Reachability git。
我正在 swiftui 中编写我的 webView 应用程序,当用户的互联网连接丢失时,我想弹出一个警报/通知程序。(所以当我的 webview 尝试加载时,他们不会闲着)
如果应用程序打开时网络更改的侦听器继续在后台运行,那将是最好的。
SO 中的大多数答案似乎都是基于 Swift 的(appdelegate、ViewDidload 等),我不知道如何使用,因为我是从 SwiftUI 开始的
提前致谢。
编辑(尝试 Lukas 提供的解决方法)
我尝试了以下。它编译并运行,但警报不会出现。它也不响应连接变化。
我的 ContentView 中有许多子视图。所以我在应用程序级别调用了 timer && 可达性。
@State var currentDate = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
let reachability = try! Reachability()
@State private var showAlert: Bool = false
它似乎不起作用:
WindowGroup {
ContentView()
.onAppear() {
if !isConnected() {
self.showAlert = true
}
}
.onReceive(timer) { _ in
if !isConnected() {
self.showAlert = true
}else{
self.showAlert = false
}
}
.alert(isPresented: $showAlert) {
Alert(title: Text("Error"), message: Text("Your internet connection is too slow."), dismissButton: .default(Text("ok")))
}
}
回答
NWPathMonitor是在 iOS 12 中引入的,作为 Reachability 的替代品。一个简单的实现如下。
我们可以公开从 返回的状态pathUpdateHandler,但是这需要您在任何想要使用该状态的地方导入 Network - 并不理想。最好创建自己的枚举来映射到 提供的每个案例NWPath.Status,您可以在此处查看值。我创建了一个只处理连接或未连接状态的程序。
所以我们创建了一个非常简单的 ObservedObject 来发布我们的状态。请注意,当监视器在自己的队列上运行时,我们可能想要更新视图中的内容,我们需要确保我们在主队列上发布。
import Network
import SwiftUI
// An enum to handle the network status
enum NetworkStatus: String {
case connected
case disconnected
}
class Monitor: ObservableObject {
private let monitor = NWPathMonitor()
private let queue = DispatchQueue(label: "Monitor")
@Published var status: NetworkStatus = .connected
init() {
monitor.pathUpdateHandler = { [weak self] path in
guard let self = self else { return }
// Monitor runs on a background thread so we need to publish
// on the main thread
DispatchQueue.main.async {
if path.status == .satisfied {
print("We're connected!")
self.status = .connected
} else {
print("No connection.")
self.status = .disconnected
}
}
}
monitor.start(queue: queue)
}
}
然后我们可以按照我们喜欢的方式使用我们的 Monitor 类,您可以将它用作 StateObject,就像我在下面所做的那样,或者您可以将它用作 EnvironmentObject。这是你的选择。理想情况下,您的应用程序中应该只有此类的一个实例。
struct ContentView: View {
@StateObject var monitor = Monitor()
// @EnvironmentObject var monitor: Monitor
var body: some View {
Text(monitor.status.rawValue)
}
}
在运行 iOS 14.2 的 iPad Pro 上的 Playgrounds 中以及在 iOS 14.3 上使用 iPhone X(真实设备)在 Xcode 12.2 上进行测试。