bad - Detección de cambios en la conectividad de la red mediante la accesibilidad, NSNotification y Network Link Conditioner en Swift
reachability ios (8)
Estoy tratando de integrar la detección de conectividad de red en mi aplicación, sin embargo, parece que en algún momento he cometido un error, ya que mis cambios de red no se detectan / imprimen en la consola.
Como se menciona en la publicación, actualmente estoy usando estas siguientes clases y herramientas para el trabajo:
-
Accesibilidad
{.h, .m}
-
NSNotificationCenter
- Acondicionador de enlace de red
Código
En
AppDelegate.Swift
, configuré
NSNotificationCenter
para detectar cambios:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// ...
// A: Checks if the device is connected to the internet
var defaultCenter: Void = NSNotificationCenter().addObserver(self, selector:"checkForReachability", name: kReachabilityChangedNotification, object: nil)
}
En la misma clase
AppDelegate
, también he creado esta función para que se active siempre que haya un cambio:
func checkForReachability () {
var networkReachability = Reachability.reachabilityForInternetConnection()
networkReachability.startNotifier()
var remoteHostStatus = networkReachability.currentReachabilityStatus()
if (remoteHostStatus.value == NotReachable.value) {
println("Not Reachable")
} else if (remoteHostStatus.value == ReachableViaWiFi.value) {
println("Reachable via Wifi")
} else {
println("Reachable")
}
}
Sin embargo, cuando uso el Acondicionador de enlace de red para manipular y simular cambios en las condiciones, no he podido ver ninguno de esos cambios reflejados en la consola. Cualquier ayuda sería genial!
1) Instale pod o agregue ReachabilitySwift en su proyecto
2) en AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(self.checkForReachability(_:)), name: "ReachabilityChangedNotification", object: nil);
do {
try self.reachability = Reachability.reachabilityForInternetConnection()
}
catch {
print(error)
}
do {
try self.reachability.startNotifier()
}
catch {
print(error)
}
return true
}
3)
func checkForReachability(notification:NSNotification) {
let networkReachability = notification.object as! Reachability;
let remoteHostStatus = networkReachability.currentReachabilityStatus
if (remoteHostStatus == .NotReachable) {
print("Not Reachable")
}
else if (remoteHostStatus == .ReachableViaWiFi || remoteHostStatus == .ReachableViaWWAN) {
print("Reachable via Wifi or via WWAN")
}
}
Basado en esta solución de código abierto Envuelto en clase
Swift 5
import Foundation
final class ReachabilityHandler {
private var reachability: Reachability? = Reachability()
// MARK: - LifeCycle
init() {
configure()
}
deinit {
NotificationCenter.default.removeObserver(self)
reachability?.stopNotifier()
}
// MARK: - Private
private func configure() {
NotificationCenter.default.addObserver(self,
selector: #selector(ReachabilityHandler.checkForReachability(notification:)),
name: Notification.Name.reachabilityChanged,
object: nil)
try? reachability?.startNotifier()
}
@objc private func checkForReachability(notification: NSNotification) {
let networkReachability = notification.object as? Reachability
if let remoteHostStatus = networkReachability?.connection {
switch remoteHostStatus {
case .none:
case .wifi,
.cellular:
}
}
}
}
En
AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
private var rechabilityObserver: ReachabilityHandler?
var window: UIWindow?
// MARK: - LifeCycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
rechabilityObserver = ReachabilityHandler()
return true
}
}
Debe crear un objeto de Accesibilidad
antes de
poder recibir notificaciones de él.
Además, asegúrese de llamar al método
startNotifier()
en el objeto de accesibilidad que cree.
Este sería un ejemplo de cómo hacerlo dentro del delegado de su aplicación:
class AppDelegate: UIResponder, UIApplicationDelegate
{
private var reachability:Reachability!;
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
{
NSNotificationCenter.defaultCenter().addObserver(self, selector:"checkForReachability:", name: kReachabilityChangedNotification, object: nil);
self.reachability = Reachability.reachabilityForInternetConnection();
self.reachability.startNotifier();
}
@objc func checkForReachability(notification:NSNotification)
{
// Remove the next two lines of code. You cannot instantiate the object
// you want to receive notifications from inside of the notification
// handler that is meant for the notifications it emits.
//var networkReachability = Reachability.reachabilityForInternetConnection()
//networkReachability.startNotifier()
let networkReachability = notification.object as Reachability;
var remoteHostStatus = networkReachability.currentReachabilityStatus()
if (remoteHostStatus.value == NotReachable.value)
{
println("Not Reachable")
}
else if (remoteHostStatus.value == ReachableViaWiFi.value)
{
println("Reachable via Wifi")
}
else
{
println("Reachable")
}
}
}
Le recomiendo que eche un vistazo a la documentación de NSNotificationCenter y NSNotification . De esa manera, estará más familiarizado con la forma de trabajar con las notificaciones la próxima vez que surja algo como esto.
Swift 3
NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil)
let reachability: Reachability = Reachability.forInternetConnection()
reachability.startNotifier()
En lugar de contaminar el
AppDelegate.swift
con devoluciones de llamada de observador, recomendaría agregar observadores solo en los controladores de vista relevantes.
AppDelegate.swift
import ReachabilitySwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
var reachability: Reachability?
func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool
{
self.reachability = Reachability()
do
{
try reachability?.startNotifier()
}
catch
{
print( "ERROR: Could not start reachability notifier." )
}
return true
}
class func sharedAppDelegate() -> AppDelegate?
{
return UIApplication.shared.delegate as? AppDelegate
}
// Remaining functions
}
Ejemplo de un ViewController:
class ExampleVC: UIViewController
{
override func viewDidLoad()
{
// Add reachability observer
if let reachability = AppDelegate.sharedAppDelegate()?.reachability
{
NotificationCenter.default.addObserver( self, selector: #selector( self.reachabilityChanged ),name: ReachabilityChangedNotification, object: reachability )
}
}
@objc private func reachabilityChanged( notification: NSNotification )
{
guard let reachability = notification.object as? Reachability else
{
return
}
if reachability.isReachable
{
if reachability.isReachableViaWiFi
{
print("Reachable via WiFi")
}
else
{
print("Reachable via Cellular")
}
}
else
{
print("Network not reachable")
}
}
}
Respuesta actualizada de AR Younce para Swift 2:
func checkForReachability(notification:NSNotification) {
if let networkReachability = notification.object as? Reachability {
let remoteHostStatus = networkReachability.currentReachabilityStatus()
if (remoteHostStatus == NotReachable) {
print("Not Reachable")
}
else if (remoteHostStatus == ReachableViaWiFi) {
print("Reachable via Wifi")
}
else {
print("Reachable")
}
} else {
print("Unknown")
}
}
Actualizado para Swift 4 / Swift 5 según @ Hardik.T
1.
Importe el archivo
Reachability.swift
desde
https://github.com/ashleymills/Reachability.swift/archive/master.zip
en su proyecto XCode
2.
Cree una nueva clase Swift:
ConnectionManager.swift
class ConnectionManager {
static let sharedInstance = ConnectionManager()
private var reachability : Reachability!
func observeReachability(){
self.reachability = Reachability()
NotificationCenter.default.addObserver(self, selector:#selector(self.reachabilityChanged), name: NSNotification.Name.reachabilityChanged, object: nil)
do {
try self.reachability.startNotifier()
}
catch(let error) {
print("Error occured while starting reachability notifications : /(error.localizedDescription)")
}
}
@objc func reachabilityChanged(note: Notification) {
let reachability = note.object as! Reachability
switch reachability.connection {
case .cellular:
print("Network available via Cellular Data.")
break
case .wifi:
print("Network available via WiFi.")
break
case .none:
print("Network is not available.")
break
}
}
}
3.
Úselo en su archivo
AppDelegate
:
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
ConnectionManager.sharedInstance.observeReachability()
return true
}
Actualizado para swift 2.1 y XCode 7:
prueba esta clase de accesibilidad altamente calificada de terceros
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
{
// Allocate a reachability object
self.reach = Reachability.reachabilityForInternetConnection()
// Tell the reachability that we DON''T want to be reachable on 3G/EDGE/CDMA
self.reach!.reachableOnWWAN = false
// 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)
self.reach!.startNotifier()
return true
}
//Reachbality Notification Response
func reachabilityChanged(notification: NSNotification) {
if self.reach!.isReachableViaWiFi() || self.reach!.isReachableViaWWAN() {
print("Service avalaible!!!")
} else {
print("No service avalaible!!!")
AppHelper.showALertWithTag(0, title: constants.AppName.rawValue, message: "Please Check Your Internet Connection!", delegate: self, cancelButtonTitle: "OK", otherButtonTitle: nil)
}
}
Swift 2.0 - Verifique la red utilizando la accesibilidad, NSNotification
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(self.checkNetworkStatus(_:)), name: "ReachabilityChangedNotification", object: nil);
do{self.reachability = try Reachability.reachabilityForInternetConnection()}catch{}
do{try self.reachability.startNotifier()}catch{}
self.checkNetworkStatus()
return true
}
Declarar variable networkStatus
var networkStatus : Reachability.NetworkStatus!
Función checkNetworkStatus ()
func checkNetworkStatus()
{
networkStatus = reachability.currentReachabilityStatus
if (networkStatus == Reachability.NetworkStatus.NotReachable)
{
print("Not Reachable")
}
else
{
print("Reachable")
}
}
OtherClass.Swift
let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
if (delegate.networkStatus!=Reachability.NetworkStatus.NotReachable)
{
// Call Webservice
}
else
{
delegate.checkNetworkStatus() //Not Reachable print
}