Использование возможности Apple для проверки доступности удаленного сервера в Swift
Я разрабатываю приложение iOS, написанное в Swift, которое общается с 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)
Всегда верно, если я подключен к сети Wi-Fi. Однако, когда я отключу Wi-Fi, это приводит к ложному, а не истинному. Я делаю что-то неправильно здесь, или класс Reachability просто не совместим с Swift/xCode 6 Beta? Я также пробовал это:
(ReachabilityInst.currentReachabilityStatus() == ReachableViaWiFi)
Но это приводит к тому, что xCode сообщает мне: "Не удалось найти перегрузку для" == ", которая принимает предоставленные аргументы", хотя оба они выглядят типа "NetworkStatus".
Спасибо заранее.
Ответы
Ответ 1
Класс Reachability, который вы используете, основан на классе Apple SCNetworkReachability, который не делает именно то, что вы надеетесь. Из документации SCNetworkReachability:
Удаленный хост считается доступным, когда пакет данных, отправленный приложение в сетевой стек, может покинуть локальное устройство. Достижимость не гарантирует, что пакет данных действительно будет полученных хостом.
Таким образом, он не создан для проверки того, действительно ли удаленный хост находится в сети, только: (1) текущие сетевые настройки позволят достичь его и (2) какими методами. После того, как вы определили, что сеть активна, вам нужно попытаться подключиться, чтобы проверить, действительно ли запущен и запущен удаленный хост.
Примечание. Этот тест:
(ReachabilityInst.currentReachabilityStatus().value == ReachableViaWiFi.value)
- правильный способ проверки - по какой-то причине NetworkStatus
является одной из немногих списков Apple созданных без макроса NS_ENUM.
Ответ 2
В быстром,
О том, что я понял о полезности достижимости, предлагаю Apple (https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html) или tonymillion (https://github.com/tonymillion/Reachability)
которые в основном одинаковы:
у вас есть 3 возможных теста:
- локальный (доступ к локальной сети, но не интернет)
- extern (можно получить доступ к интернету по IP-адресу)
- dns (можно получить доступ к Интернету и получить имя хоста)
Вы можете протестировать их соответственно, запустив уведомитель:
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()
}
Затем вы можете вызвать его в файле didFinishLaunchingWithOptions вашего приложения appDelegate:
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")
}
}
}
Вы также можете поймать событие внутри вашего приложения appDelegate, добавив NSNotificationCenter.defaultCenter(). addObserver() внутри didFinishLaunchingWithOptions, а затем добавьте в него свойство reachabilityChanged (уведомление: NSNotification).
А, также обратите внимание, что вы можете легко добавить класс достижимости в свой проект с помощью cocoapods, добавив эту строку:
pod 'Reachability', '~> 3.2'
В ваш файл pod и их после установки pod install в командной строке просто добавьте эту строку в заголовок xxx-Bridging-Header.h (где xxx - это имя вашего приложения):
#import <Reachability/Reachability.h>
Если у вас нет моста заголовка в проекте, вы можете следовать этому руководству: http://www.learnswiftonline.com/getting-started/adding-swift-bridging-header/
Не нужно добавлять systemConfiguration.framework, которая уже добавлена зависимостями pod.
Примечание. Достижимость не работает нормально в симуляторе
надеюсь, что эта помощь!
Ответ 3
Если вы ищете быструю реализацию класса Apple Reachability, вы можете взглянуть на это:
http://github.com/ashleymills/Reachability.swift
Это падение класса, используя уведомления и закрытие.
Он работает с iOS и OS X и поддерживает Cocoapod/Carthage.
Удачи!