我正在开发一个用Swift编写的iOS应用程序,它与本地网络上的HTTP服务器通信,我正在使用Apple的Reachability类来确定运行HTTP服务器的远程机器是否在线。这是代码:
...
let RemoteHost: String = "192.168.178.130"
var RemoteReachability: Reachability! = nil
var RemoteIsReachable: Bool = false
init() {
super.init()
self.RemoteReachability = Reachability(hostName: self.RemoteHost)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name: kReachabilityChangedNotification, object: self.RemoteReachability)
self.RemoteReachability.startNotifier()
self.RemoteIsReachable = (self.RemoteReachability.currentReachabilityStatus().value == ReachableViaWiFi.value)
}
func reachabilityChanged(notification: NSNotification) {
let ReachabilityInst: Reachability = notification.object as Reachability
self.RemoteIsReachable = (ReachabilityInst.currentReachabilityStatus().value == ReachableViaWiFi.value)
}
问题是无论远程机器是在线还是离线,
(ReachabilityInst.currentReachabilityStatus().value == ReachableViaWiFi.value)
只要我连接到Wifi网络,总是如此。但是,当我关闭Wifi时,它会导致错误而不是真实。我在这里做错了什么,或者Reachability类是否与Swift / xCode 6 Beta不兼容?我也试过这个:
(ReachabilityInst.currentReachabilityStatus() == ReachableViaWiFi)
但是这导致xCode告诉我“无法找到接受提供的参数的'=='的重载”,即使两者看起来都是'NetworkStatus'类型。
提前致谢。
答案 0 :(得分:32)
您正在使用的Reachability类是基于Apple的SCNetworkReachability类,它并不完全符合您的希望。来自SCNetworkReachability documentation:
当数据包发送时,远程主机被认为是可达的 应用程序进入网络堆栈,可以离开本地设备。 可达性不保证数据包实际上是 收到主持人的回复。
因此,它不是用于测试远程主机是否实际在线,只是(1)当前网络设置是否允许尝试到达它和(2)通过什么方法。一旦确定网络处于活动状态,您就需要尝试连接以查看远程主机是否实际启动并运行。
注意:此测试:
(ReachabilityInst.currentReachabilityStatus().value == ReachableViaWiFi.value)
是检查的正确方法 - 由于某种原因NetworkStatus
是为数不多的Apple enumerations created without the NS_ENUM macro之一。
答案 1 :(得分:11)
关于我对 Apple (https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html)或 tonymillion (https://github.com/tonymillion/Reachability)提出的可达性效用的理解 基本相同的是:
你有3个可能的测试:
您可以通过以下方式启动通知程序来分别测试它们:
let wifiReachability = Reachability. reachabilityForLocalWiFi()
wifiReachability.startNotifier()
let internetReachability = Reachability.reachabilityForInternetConnection()
hostReachability.startNotifier()
let hostReachability = Reachability(hostName:"www.apple.com")
hostReachability.startNotifier()
这将触发您可以使用此方法捕获的通知: NSNotificationCenter.defaultCenter()。addObserver()
所以要使用它们你可以做类似的事情:
在你的appDelegate中创建一个函数,它将实例化通知程序:
func startReachabilityTest()
{
// Allocate a reachability object to test internet access by hostname
let reach = Reachability(hostName: "www.apple.com")
// Tell the reachability that we DON'T want to be reachable on 3G/EDGE/CDMA
//reach.reachableOnWWAN = false
reach.startNotifier()
}
然后你可以在appDelegate的didFinishLaunchingWithOptions中调用它:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.startReachabilityTest();
}
如果想在任何viewController中捕获事件,只需将此行添加到viewDidLoad:
override func viewDidLoad()
{
// Here we set up a NSNotification observer. The Reachability that caused the notification
// is passed in the object parameter
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "reachabilityChanged:",
name: kReachabilityChangedNotification,
object: nil)
}
并添加此方法方法以对事件做出反应:
func reachabilityChanged(notice: NSNotification)
{
println("reachability changed")
let reach = notice.object as? Reachability
if let remoteHostStatus = reach?.currentReachabilityStatus()
{
if remoteHostStatus == NetworkStatus.NotReachable
{
println("not reachable")
}
else
{
println("reachable")
}
}
}
您还可以通过在didFinishLaunchingWithOptions中添加 NSNotificationCenter.defaultCenter()。addObserver()来在appDelegate中捕获事件,然后在其中添加 reachabilityChanged(注意:NSNotification)
啊,还要注意,通过添加以下行,您可以使用cocoapods轻松地将可达性类添加到项目中:
pod 'Reachability', '~> 3.2'
在命令行中 pod install 之后,将您的pod文件添加到 xxx-Bridging-Header.h 头文件中(其中xxx是名称)你的应用程序):
#import <Reachability/Reachability.h>
如果您的项目中没有桥接标题,则可以按照本教程进行操作:http://www.learnswiftonline.com/getting-started/adding-swift-bridging-header/
无需添加已由pod依赖项添加的systemConfiguration.framework。
注意:可达性在模拟器中不能正常工作
希望这有帮助!答案 2 :(得分:2)
如果您正在寻找Swift实施Apple的Reachability类,您可以看一下:
http://github.com/ashleymills/Reachability.swift
使用通知和闭包,这是课堂上的一个下降。
适用于iOS和OS X,并支持Cocoapod / Carthage。
祝你好运!答案 3 :(得分:0)
使用组合和可达性:
import Combine
import Reachability
import os
class ReachabilityStore: ObservableObject {
private var reachability: Reachability
@Published var reachable: Bool = false
@Published var reachableViaWifi: Bool = false
@Published var reachableViaCellular: Bool = false
init() {
reachability = try! Reachability()
reachability.whenReachable = { [weak self] reachability in
guard let self = self else { return }
self.reachable = true
self.reachableViaWifi = reachability.connection == .wifi
self.reachableViaCellular = !self.reachableViaWifi
os_log(
"Reachable via %{public}s",
self.reachableViaWifi ? "WiFi" : "Cellular"
)
}
reachability.whenUnreachable = { [weak self] _ in
guard let self = self else { return }
os_log("Unreachable")
self.reachable = false
self.reachableViaWifi = false
self.reachableViaCellular = false
}
do {
try reachability.startNotifier()
} catch {
os_log("Unable to start reachability notifier.")
}
}
}