【问题标题】:How to know whether actual internet is available or not in Swift?如何在 Swift 中知道实际的互联网是否可用?
【发布时间】:2018-09-28 07:38:02
【问题描述】:

我想在我的 WiFi 路由器颜色从 Green 变为 Red

时收到通知

我正在制作一个应用程序,它会通过 Swift 中的菜单栏告诉你是在线还是离线,它是开源的,可以在 https://github.com/deadcoder0904/net-alert 找到

我想知道当 WiFi 颜色在 Swift 中发生变化时是否可以得到通知。

我不能经常 ping 我的服务器来知道颜色发生了变化,因为这会浪费 Internet 资源。

那么在 Swift 中可以知道这一点吗?

【问题讨论】:

  • 你想为任何 wifi 做这个吗?或者只是针对某些特定的 SSID? NetworkExtension 框架可能会有所帮助。
  • 任何 WiFi。我需要制作一个简单的菜单栏,如果可以访问互联网,则将颜色更改为green,如果无法访问互联网,则更改为red。因此,如果 WiFi 变为 red,那么我需要以某种方式知道它,以便我可以将菜单栏更改为 red 并且与 green 相同 :)
  • 你能比“不起作用”更具体吗? (在下面的问题中注明。)您的意思是您的可达性回调不会被调用吗?他们确实被调用但值错误?你如何测试这个?目前还不是很清楚你问的具体问题是什么。
  • 您的带宽有多有限,ping 会“浪费 Internet 资源”? :O
  • 许多、许多、许多应用程序为此目的使用某种心跳或健康检查(即持续轮询)。在您证明它对网络性能有重大影响之前,我不会担心过早的优化。

标签: ios swift notifications reachability


【解决方案1】:

首先,我将从 iOS 的角度来回答这个问题。但是您的 GitHub 演示适用于 macOS。我认为基础是相同的。

我会用面向协议的方法来解决这个问题。


更新:

经过大量搜索,我发现了 Connectivity 包装器的出色实现。如果您想了解更多信息,甚至还有一篇描述性博文Solving the Captive Portal Problem on iOS此实现能够处理实际的互联网可用/不可用状态。

注意:不想继续阅读? Here 是我将简要说明的工作版本。导航栏会以 GreenRed 颜色反映不同的连接状态。

定义协议:

当连接发生任何变化时,该协议将帮助任何感兴趣的对象得到通知。

protocol ConnectivityNotifiable {
    var connectivity: Connectivity { get }
    func startNotifyingConnectivityChangeStatus()
    func stopNotifyingConnectivityChangeStatus()
    func connectivityChanged(toStatus: ConnectivityStatus)
}

// Provide some default implementation through protocol extension
extension ConnectivityNotifiable {
    func startNotifyingConnectivityChangeStatus() {
        connectivity.isPollingEnabled = true
        connectivity.startNotifier()
        connectivity.whenConnected = { connectivity in
            self.connectivityChanged(toStatus: connectivity.status)
        }
        connectivity.whenDisconnected = { connectivity in
            self.connectivityChanged(toStatus: connectivity.status)
        }
    }
    func stopNotifyingConnectivityChangeStatus() {
        connectivity.stopNotifier()
    }
}

符合协议:

符合ConnectivityNotifiable 协议将向任何感兴趣的对象添加功能,以便在连接状态更改时得到通知。监控之类的。

class ViewController: UIViewController, ConnectivityNotifiable {

    // ConnectivityNotifiable protocol requirement
    let connectivity = Connectivity()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Invoke the default implementation of the ConnectivityNotifiable protocol
        // requirement to be able to be notified
        startNotifyingConnectivityChangeStatus()

        // Reminder:
        // Don't forget to invoke stopNotifyingConnectivityChangeStatus() when
        // you are done or when the lifecycle of your controller ends
    }

    // ConnectivityNotifiable protocol requirement
    func connectivityChanged(toStatus: ConnectivityStatus) {
        // Everytime any change happens in the network connectivity 
        // this method will be invoked with appropriate connection status
        switch toStatus {

        case .connected, 
             .connectedViaWiFi, 
             .connectedViaCellular:
            // Connected/Internet available. Update any UI component

        case .notConnected, 
             .connectedViaWiFiWithoutInternet, 
             .connectedViaCellularWithoutInternet:
            // Disconnected/Internet not available. Update any UI component
        }
    }
}


旧答案

注意:如果您使用的是Reachability 中的最新release,则不需要基于NotificationCenter 的解决方案来获取可达性更改通知。它完全适用于基于闭包的方法。


不想知道如何实现这一目标? Here 是为 iOS 平台制作的工作版本。克隆 repo 并检查自己。导航栏会以 GreenOrangeRed 颜色反映不同的连接状态。

定义协议:

当可达性发生任何变化时,该协议将帮助任何感兴趣的对象得到通知。

protocol Reachable {
    var reachability: Reachability { get }
    func startMonitoringReachabilityChangeStatus()
    func reachabilityChanged(to: Reachability.Connection)
}

extension Reachable {
    func startMonitoringReachabilityChangeStatus() {
        do {
            try reachability.startNotifier()
        } catch {
            print(error.localizedDescription)
        }
        reachability.whenReachable = { reachability in
            self.reachabilityChanged(to: reachability.connection)
        }
        reachability.whenUnreachable = { reachability in
            self.reachabilityChanged(to: reachability.connection)
        }
    }
}

遵守协议:

符合Reachable 协议将向任何感兴趣的对象添加功能,以便在可达性状态更改时得到通知。监控之类的。

class ViewController: UIViewController, Reachable {

    // Reachable protocol requirement
    let reachability: Reachability = Reachability()!

    override func viewDidLoad() {
        super.viewDidLoad()

        // initial reachability checkup
        reachabilityChanged(to: reachability.connection)

        // Invoke the default implementation of the Reachable protocol requirement 
        // to be able to be notified
        startMonitoringReachabilityChangeStatus()
    }

    // Reachable protocol requirement
    func reachabilityChanged(to: Reachability.Connection) {
        // Everytime any change happens in the network connectivity 
        // this method will be invoked with appropriate connection status
        switch to {
        case .wifi:
            DispatchQueue.main.async {
                // Update any UI component
            }
        case .cellular:
            DispatchQueue.main.async {
                // Update any UI component
            }
        case .none:
            DispatchQueue.main.async {
                // Update any UI component
            }
        }
    }
}

【讨论】:

  • 我试过了,但没用,所以我保留了相同的旧版本,因为它们的工作方式相似:) 虽然感谢您的解决方案
  • @deadcoder0904 嘿,我已经用新的实现更新了答案。我希望这应该满足您的要求:)
  • 我刚刚接受了您的回答,因为它适用于someone。谢谢你。不过我还没有尝试:)
  • ConnectivityNotifiable 协议新答案对我有用。
  • 但它一直在检查网络,它会影响电池寿命吗?
【解决方案2】:

我浏览了代码,当互联网连接中断时,您所做的方式不会通知您,它只是在运行时检查是否有连接。 为了实现您想要的,我们需要添加通知

首先,声明可达性变量

 private var reachability:Reachability!;

然后在appdelegatedidFinishLaunchingWithOptions 方法中添加以下代码

 self.reachability = Reachability.init()
         NotificationCenter.default.addObserver(self, selector: #selector(checkForReachability(notification:)), name: .reachabilityChanged, object: reachability)
        do{
            try reachability.startNotifier()
        }catch{
            print("could not start reachability notifier")
        }

我们所做的是初始化可达性变量并创建一个通知观察器,以在通知器的帮助下检测连接状态何时发生变化。

最后是选择器方法

@objc func checkForReachability(notification:NSNotification)
    {
        let reachability = notification.object as! Reachability
        switch reachability.connection {
        case .wifi:
            print("Reachable via WiFi")
        case .cellular:
            print("Reachable via Cellular")
        case .none:
            print("Network not reachable")
        }
    }

就是这样,从现在开始,当互联网连接中断时,我们会收到通知,在上述方法中您可以更改菜单栏图标的颜色。

【讨论】:

  • 嘿,Daris,它不仅在运行时有效,而且在中断时也有效。如果我从顶部菜单栏下拉菜单中关闭 WiFi,它会变成红色,当我再次打开时,它会变成绿色。我不清楚您的解决方案适用于哪个用例。想详细说明一下吗?
  • 就像你刚刚解释了这段代码的使用一样,当 wifi 关闭时,它应该变成红色,当重新打开时,条应该是绿色的。所以你可以在各自的情况下改变颜色。
  • 啊,原来的(我的解决方案)和你的一样,@nayem 在上面的答案中也说过:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2022-12-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 2012-05-24
相关资源
最近更新 更多