2

我正在开发一个复杂的应用程序,我想在每个从服务器接收数据的 ViewController 上测试两个主机的互联网可达性我目前正在使用这个库来实现可达性

https://github.com/ashleymills/Reachability.swift

我想创建一个简单的方法或扩展来检查互联网和主机的可达性我已经使用了下面库中的示例代码:`import UIKit

import Reachability

class VC22: UIViewController {

@IBOutlet weak var networkStatus: UILabel!
@IBOutlet weak var hostNameLabel: UILabel!

var reachability: Reachability?

override func viewDidLoad() {
    super.viewDidLoad()

    // Start reachability without a hostname intially
    setupReachability(nil, useClosures: true)
    startNotifier()

    // After 5 seconds, stop and re-start reachability, this time using a hostname
    let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5)
    DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
        self.stopNotifier()
        self.setupReachability("http://81.28.42.42:4242/", useClosures: true)
        self.startNotifier()

        let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5)
        DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
            self.stopNotifier()
            self.setupReachability("invalidhost", useClosures: true)
            self.startNotifier()            }

    }
}

func setupReachability(_ hostName: String?, useClosures: Bool) {
    hostNameLabel.text = hostName != nil ? hostName : "No host name"

    print("--- set up with host name: \(hostNameLabel.text!)")

    let reachability = hostName == nil ? Reachability() : Reachability(hostname: hostName!)
    self.reachability = reachability

    if useClosures {
        reachability?.whenReachable = { reachability in
            DispatchQueue.main.async {
                self.updateLabelColourWhenReachable(reachability)
            }
        }
        reachability?.whenUnreachable = { reachability in
            DispatchQueue.main.async {
                self.updateLabelColourWhenNotReachable(reachability)
            }
        }
    } else {
        NotificationCenter.default.addObserver(self, selector: #selector(VC22.reachabilityChanged(_:)), name: ReachabilityChangedNotification, object: reachability)
    }
}

func startNotifier() {
    print("--- start notifier")
    do {
        try reachability?.startNotifier()
    } catch {
        networkStatus.textColor = .red
        networkStatus.text = "Unable to start\nnotifier"
        return
    }
}

func stopNotifier() {
    print("--- stop notifier")
    reachability?.stopNotifier()
    NotificationCenter.default.removeObserver(self, name: ReachabilityChangedNotification, object: nil)
    reachability = nil
}

func updateLabelColourWhenReachable(_ reachability: Reachability) {
    print("\(reachability.description) - \(reachability.currentReachabilityString)")
    if reachability.isReachableViaWiFi {
        self.networkStatus.textColor = .green
    } else {
        self.networkStatus.textColor = .blue
    }

    self.networkStatus.text = reachability.currentReachabilityString
}

func updateLabelColourWhenNotReachable(_ reachability: Reachability) {
    print("\(reachability.description) - \(reachability.currentReachabilityString)")

    self.networkStatus.textColor = .red

    self.networkStatus.text = reachability.currentReachabilityString
}


func reachabilityChanged(_ note: Notification) {
    let reachability = note.object as! Reachability

    if reachability.isReachable {
        updateLabelColourWhenReachable(reachability)
    } else {
        updateLabelColourWhenNotReachable(reachability)
    }
}

deinit {
    stopNotifier()
}

}

这很好,但我只需要一个布尔值来告诉我它是否已连接,可以通过应用程序重复使用

更新目前我正在使用以下课程:

import Foundation
import SystemConfiguration

public class Reachability {

    class func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }

        var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired

        return isReachable && !needsConnection

    }
}

并在 viewControllers 中使用,如下所示:

 if Reachability.isConnectedToNetwork() == true {
        print("Internet connection OK")

      JSONParseFunction()

} else {
    print("Internet connection FAILED")
    let alert = UIAlertView(title: "You are not connect to internet", message: "please check you connectivity", delegate: nil, cancelButtonTitle: "OK")
    alert.show()
}

这样我只检查互联网我需要检查主机和互联网

4

1 回答 1

2

是否有理由不只是将其放入您的AppDelegate并订阅那里的观察者而不是在特定的vc上进行?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        prepareReachabilityObserver()
        return true
    }

    private func prepareReachabilityObserver() {
        AppDelegate.reachability.whenUnreachable = { reachability in
            DispatchQueue.main.async {
                print("Not reachable")
            }
        }

        do {
            try AppDelegate.reachability.startNotifier()
        } catch {
            print("Unable to start notifier")
        }
    }

host verification extension部分而言,我可能会选择类似的东西:

extension UIViewController {
    internal func isReachable() -> Bool {
            //this is the function you already have.
    }
}

然后您可以在每个视图控制器中使用它

self.isReachable() //'self' is a UIViewController in this case.

除此之外,我无法理解您的问题,因为您似乎已经解决了这个问题。

编辑:我想我现在明白你的问题了。您想检查您是否可以访问以及您传递的主机名是否也可以访问。我不认为同时处理这两个问题是最好的主意,因为一个是可达性问题('我可以得到一个传出连接吗?'),另一个是一个连接问题('我可以从这个偏远的地方?'或'这个请求是否超时?')。

我目前处理它的方式是 AppDelegate 中的可达性,然后以逐个请求的方式处理超时(然后您可以在网络内容范围内概括)。更具体地说: AppDelegate设置可达性。然后我有一个RequestsManager处理服务调用的配置timeout

然后您可以执行以下操作:

RequestManager.makeRequest("https://an.endpoint.of.yours",
        onSuccess: {},
        onFailure: { //Here goes your timeout behaviour.
})

我在哪里传递主机名? 老实说,我认为这是一种不必要的行为。你没有try to open door ,然后open door。你只是试试看你是否成功。这里也是一样。你尝试提出请求,它成功了吗?惊人的。不是吗?相应处理。如果失败是因为端点已关闭还是因为您没有有效的数据计划或网络已关闭,您(应用程序)会关心什么?无论哪种方式,请求都会超时,这就是您所关心的。

同样,这一切都假设我真的理解你,我不是 100% 肯定。

于 2017-05-02T19:59:57.737 回答