为可达性创建易于使用的扩展/功能(主机/互联网WIFI,蜂窝)

时间:2017-05-02 19:30:39

标签: ios swift reachability reachability-swift

我正在开发一个复杂的应用程序,我想在每个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()
}

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

1 个答案:

答案 0 :(得分: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.
    }
}

然后可以通过

在每个viewcontroller中使用它
self.isReachable() //'self' is a UIViewController in this case.

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

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

我目前处理它的方式是在AppDelegate之类的可达性,然后按请求方式处理超时(然后可以在网络范围内进行概括)。 更具体: AppDelegate设置了可达性。然后我有一个RequestsManager来处理具有已配置timeout的服务调用。

然后你可以做类似的事情:

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

我在哪里传递主机名? 我认为这是不必要的行为,说实话。您没有try to open door ,然后open door。你只是试着看看你是否成功了。这是一样的。您尝试提出请求,是否成功?真棒。不是吗?处理相应。如果失败是因为端点关闭或者您没有工作数据计划或网络故障,那么您(应用程序)如何关心?请求超时,这就是你关心的。

同样,这是假设我真正了解你,我不是百分之百确定。