reachable networkreachabilitymanager internet check ios swift xcode reachability

ios - networkreachabilitymanager - swift check internet connection



Compruebe la conexión a internet con Swift (16)

Apple ha introducido Network Framework en iOS12.

import Foundation import Network class NetworkReachability { var pathMonitor: NWPathMonitor! var path: NWPath? lazy var pathUpdateHandler: ((NWPath) -> Void) = { path in self.path = path if path.status == NWPath.Status.satisfied { print("Connected") } else if path.status == NWPath.Status.unsatisfied { print("unsatisfied") } else if path.status == NWPath.Status.requiresConnection { print("requiresConnection") } } let backgroudQueue = DispatchQueue.global(qos: .background) init() { pathMonitor = NWPathMonitor() pathMonitor.pathUpdateHandler = self.pathUpdateHandler pathMonitor.start(queue: backgroudQueue) } func isNetworkAvailable() -> Bool { if let path = self.path { if path.status == NWPath.Status.satisfied { return true } } return false } }

Cuando intento buscar una conexión a Internet en mi iPhone, recibo muchos errores. ¿Alguien puede ayudarme a arreglar esto?

El código:

import Foundation import SystemConfiguration public class Reachability { class func isConnectedToNetwork() -> Bool { var zeroAddress = sockaddr_in() zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress)) zeroAddress.sin_family = sa_family_t(AF_INET) let defaultRouteReachability = withUnsafePointer(&zeroAddress) { SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) } var flags: SCNetworkReachabilityFlags = 0 if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 { return false } let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0 let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 return (isReachable && !needsConnection) ? true : false } }

Los errores con el código:

Si no se puede leer, el error 1 dice:

''Int'' no es convertible a ''SCNetworkReachabilityFlags''

Error 2 y 3:

No se pudo encontrar una sobrecarga para ''init'' que acepte los argumentos proporcionados


Aunque no responde directamente a su pregunta, me gustaría mencionar que Apple recientemente tuvo esta charla:

https://developer.apple.com/videos/play/wwdc2018/714/

Alrededor de las 09:55 él habla sobre hacer estas cosas que usted está preguntando:

  1. Verifica la conexión
  2. Si la conexión -> Hacer algo
  3. Si no hay conexión -> Hacer otra cosa (¿esperar? ¿Reintentar?)

Sin embargo, esto tiene algunas trampas:

  • ¿Qué pasa si en el paso 2 dice que tiene una conexión, pero 0.5 segundos después no la tiene?
  • ¿Qué pasa si el usuario está detrás de un proxy?
  • Por último, pero no menos importante, ¿qué pasa si algunas respuestas aquí no pueden determinar la conectividad correcta? (Estoy seguro de que si cambias rápidamente tu conexión, vas a wi-fi y la apagas (solo hazlo complicado), casi nunca puede determinar correctamente si tengo una conexión o no).
  • Cita del video: "No hay forma de garantizar si una operación futura tendrá éxito o no"

Los siguientes puntos son algunas de las mejores prácticas según Apple:

Según la charla, no debería haber ninguna razón para verificar previamente si tiene conexión a Internet o no, ya que puede no ser precisa en el momento en que envía su solicitud al servidor .


Con la ayuda del siguiente código, puede verificar la conexión a Internet tanto para la red celular como para wifi. idioma - Swift 3.0

import UIKit import Foundation import SystemConfiguration class NetworkConnection: UIViewController { 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) guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { SCNetworkReachabilityCreateWithAddress(nil, $0) } }) else { return false } var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0) if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false { return false } let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 return (isReachable && !needsConnection) } class func checkConnection(sender:UIViewController){ if NetworkConnection.isConnectedToNetwork() == true { print("Connected to the internet") // Do something } else { print("No internet connection") let alertController = UIAlertController(title: "No Internet Available", message: "", preferredStyle: UIAlertControllerStyle.alert) let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){(result:UIAlertAction) -> Void in return } alertController.addAction(okAction) sender.present(alertController, animated: true, completion: nil) // Do something } } }


Esta es mi versión Esencialmente no trae nada nuevo. Lo vinculé a UIDevice.

import UIKit import SystemConfiguration extension UIDevice { open class var isConnectedToNetwork: Bool { get { var zeroAddress = sockaddr_in() zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) zeroAddress.sin_family = sa_family_t(AF_INET) guard let defaultRouteReachability: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { SCNetworkReachabilityCreateWithAddress(nil, $0) } }), var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags() as SCNetworkReachabilityFlags?, SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) else { return false } return flags.contains(.reachable) && !flags.contains(.connectionRequired) } } } print("Network status availability: " + ( UIDevice.isConnectedToNetwork ? "true" : "false" ))


He creado mi propia solución con NSTimer y Alamofire:

import Alamofire public class ConnectionHelper: NSObject { var request: Alamofire.Request? func isInternetConnected(completionHandler: Bool -> Void) { NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "requestTimeout", userInfo: nil, repeats: false) request = Alamofire .request( Method.HEAD, "http://www.testurl.com" ) .response { response in if response.3?.code == -999 { completionHandler( false ) } else { completionHandler( true ) } } } func requestTimeout() { request!.cancel() } }

El NSTimer se usa como un tiempo de espera, y se usó debido a resultados poco confiables usando el tiempo de espera de Alamofire. La solicitud debe hacerse a una URL en la que confíe para ser confiable, como su propio servidor o el servidor que aloja los servicios de los que depende.

Cuando expira el temporizador, la solicitud se cancela y los resultados se devuelven utilizando un controlador de finalización.

Uso:

ConnectionHelper().isInternetConnected() { internetConnected in if internetConnected { // Connected } else { // Not connected } }


Para Swift 3, no podría usar solo el alcance de las soluciones RAJAMOHAN-S, ya que devuelve "verdadero" si hay WiFi pero no Internet. Por lo tanto, implementé una segunda validación a través de la clase URLSession y el controlador de finalización.

Aquí está toda la clase.

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 } // Working for Cellular and WIFI let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 let ret = (isReachable && !needsConnection) return ret } class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) { // 1. Check the WiFi Connection guard isConnectedToNetwork() else { completionHandler(false) return } // 2. Check the Internet Connection var webAddress = "https://www.google.com" // Default Web Site if let _ = webSiteToPing { webAddress = webSiteToPing! } guard let url = URL(string: webAddress) else { completionHandler(false) print("could not create url from: /(webAddress)") return } let urlRequest = URLRequest(url: url) let session = URLSession.shared let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in if error != nil || response == nil { completionHandler(false) } else { completionHandler(true) } }) task.resume() } }

Y a esto le llamas así, por ejemplo:

Reachability.isInternetAvailable(webSiteToPing: nil) { (isInternetAvailable) in guard isInternetAvailable else { // Inform user for example return } // Do some action if there is Internet }


Si bien es posible que no determine directamente si el teléfono está conectado a una red, la solución más simple (¿más limpia?) Sería ''hacer ping'' a Google u otro servidor (lo cual no es posible a menos que el teléfono esté conectado a una red) ):

private var urlSession:URLSession = { var newConfiguration:URLSessionConfiguration = .default newConfiguration.waitsForConnectivity = false newConfiguration.allowsCellularAccess = true return URLSession(configuration: newConfiguration) }() public func canReachGoogle() -> Bool { let url = URL(string: "https://8.8.8.8") let semaphore = DispatchSemaphore(value: 0) var success = false let task = urlSession.dataTask(with: url!) { data, response, error in if error != nil { success = false } else { success = true } semaphore.signal() } task.resume() semaphore.wait() return success }

Si le preocupa que el servidor pueda estar inactivo o que pueda bloquear su IP, siempre puede hacer ping a varios servidores de manera similar y devolver si alguno de ellos es accesible. O haga que alguien configure un servidor dedicado solo para este propósito.


Si está usando Alamofire, puede hacer algo como esto:

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() configuration.timeoutIntervalForRequest = 15 //Set timeouts in sec configuration.timeoutIntervalForResource = 15 let alamoFireManager = Alamofire.Manager(configuration:configuration) alamoFireManager?.request(.GET, "https://yourURL.com", parameters: headers, encoding: .URL) .validate() .responseJSON { response in if let error = response.result.error { switch error.code{ case -1001: print("Slow connection") return case -1009: print("No Connection!") return default: break } }


aquí mi solución para swift 2.3 con lib ( Reachability.swift )

Entra en tu Podfile y agrega:

pod ''ReachabilitySwift'', ''~> 2.4'' // swift 2.3

Luego en tu terminal :

pod install

Luego cree un nuevo archivo ReachabilityManager y agregue el siguiente código:

import Foundation import ReachabilitySwift enum ReachabilityManagerType { case Wifi case Cellular case None } class ReachabilityManager { static let sharedInstance = ReachabilityManager() private var reachability: Reachability! private var reachabilityManagerType: ReachabilityManagerType = .None private init() { do { self.reachability = try Reachability.reachabilityForInternetConnection() } catch { print("Unable to create Reachability") return } NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ReachabilityManager.reachabilityChanged(_:)),name: ReachabilityChangedNotification,object: self.reachability) do{ try self.reachability.startNotifier() }catch{ print("could not start reachability notifier") } } @objc private func reachabilityChanged(note: NSNotification) { let reachability = note.object as! Reachability if reachability.isReachable() { if reachability.isReachableViaWiFi() { self.reachabilityManagerType = .Wifi } else { self.reachabilityManagerType = .Cellular } } else { self.reachabilityManagerType = .None } } } extension ReachabilityManager { func isConnectedToNetwork() -> Bool { return reachabilityManagerType != .None } }

Cómo usarlo:

ingrese a su AppDelegate.swift y agregue el código a continuación:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { ReachabilityManager.sharedInstance }

Luego, cuando desee verificar si el dispositivo está conectado a Internet, haga lo siguiente:

if ReachabilityManager.sharedInstance.isConnectedToNetwork() { // Connected } else { // Not connected }


Acabo de descubrir esto por mí mismo.

Xcode: 7.3.1, iOS 9.3.3

Usando github.com/ashleymills/Reachability.swift como Reachability.swift en mi proyecto, creé la siguiente función:

func hasConnectivity() -> Bool { do { let reachability: Reachability = try Reachability.reachabilityForInternetConnection() let networkStatus: Int = reachability.currentReachabilityStatus.hashValue return (networkStatus != 0) } catch { // Handle error however you please return false } }

Simplemente llame a hasConnectivity() siempre que necesite verificar una conexión. Esto funciona tanto para Wifi como para Celular.

Agregando Ashleymills''s Reachability.swift para que las personas no tengan que moverse entre sitios:

Copyright (c) 2014, Ashley Mills All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Reachability.swift version 2.2beta2 import SystemConfiguration import Foundation public enum ReachabilityError: ErrorType { case FailedToCreateWithAddress(sockaddr_in) case FailedToCreateWithHostname(String) case UnableToSetCallback case UnableToSetDispatchQueue } public let ReachabilityChangedNotification = "ReachabilityChangedNotification" func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) { let reachability = Unmanaged<Reachability>.fromOpaque(COpaquePointer(info)).takeUnretainedValue() dispatch_async(dispatch_get_main_queue()) { reachability.reachabilityChanged(flags) } } public class Reachability: NSObject { public typealias NetworkReachable = (Reachability) -> () public typealias NetworkUnreachable = (Reachability) -> () public enum NetworkStatus: CustomStringConvertible { case NotReachable, ReachableViaWiFi, ReachableViaWWAN public var description: String { switch self { case .ReachableViaWWAN: return "Cellular" case .ReachableViaWiFi: return "WiFi" case .NotReachable: return "No Connection" } } } // MARK: - *** Public properties *** public var whenReachable: NetworkReachable? public var whenUnreachable: NetworkUnreachable? public var reachableOnWWAN: Bool public var notificationCenter = NSNotificationCenter.defaultCenter() public var currentReachabilityStatus: NetworkStatus { if isReachable() { if isReachableViaWiFi() { return .ReachableViaWiFi } if isRunningOnDevice { return .ReachableViaWWAN } } return .NotReachable } public var currentReachabilityString: String { return "/(currentReachabilityStatus)" } private var previousFlags: SCNetworkReachabilityFlags? // MARK: - *** Initialisation methods *** required public init(reachabilityRef: SCNetworkReachability) { reachableOnWWAN = true self.reachabilityRef = reachabilityRef } public convenience init(hostname: String) throws { let nodename = (hostname as NSString).UTF8String guard let ref = SCNetworkReachabilityCreateWithName(nil, nodename) else { throw ReachabilityError.FailedToCreateWithHostname(hostname) } self.init(reachabilityRef: ref) } public class func reachabilityForInternetConnection() throws -> Reachability { var zeroAddress = sockaddr_in() zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress)) zeroAddress.sin_family = sa_family_t(AF_INET) guard let ref = withUnsafePointer(&zeroAddress, { SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) }) else { throw ReachabilityError.FailedToCreateWithAddress(zeroAddress) } return Reachability(reachabilityRef: ref) } public class func reachabilityForLocalWiFi() throws -> Reachability { var localWifiAddress: sockaddr_in = sockaddr_in(sin_len: __uint8_t(0), sin_family: sa_family_t(0), sin_port: in_port_t(0), sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) localWifiAddress.sin_len = UInt8(sizeofValue(localWifiAddress)) localWifiAddress.sin_family = sa_family_t(AF_INET) // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 let address: UInt32 = 0xA9FE0000 localWifiAddress.sin_addr.s_addr = in_addr_t(address.bigEndian) guard let ref = withUnsafePointer(&localWifiAddress, { SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) }) else { throw ReachabilityError.FailedToCreateWithAddress(localWifiAddress) } return Reachability(reachabilityRef: ref) } // MARK: - *** Notifier methods *** public func startNotifier() throws { guard !notifierRunning else { return } var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque()) if !SCNetworkReachabilitySetCallback(reachabilityRef!, callback, &context) { stopNotifier() throw ReachabilityError.UnableToSetCallback } if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef!, reachabilitySerialQueue) { stopNotifier() throw ReachabilityError.UnableToSetDispatchQueue } // Perform an intial check dispatch_async(reachabilitySerialQueue) { () -> Void in let flags = self.reachabilityFlags self.reachabilityChanged(flags) } notifierRunning = true } public func stopNotifier() { defer { notifierRunning = false } guard let reachabilityRef = reachabilityRef else { return } SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) } // MARK: - *** Connection test methods *** public func isReachable() -> Bool { let flags = reachabilityFlags return isReachableWithFlags(flags) } public func isReachableViaWWAN() -> Bool { let flags = reachabilityFlags // Check we''re not on the simulator, we''re REACHABLE and check we''re on WWAN return isRunningOnDevice && isReachable(flags) && isOnWWAN(flags) } public func isReachableViaWiFi() -> Bool { let flags = reachabilityFlags // Check we''re reachable if !isReachable(flags) { return false } // Must be on WiFi if reachable but not on an iOS device (i.e. simulator) if !isRunningOnDevice { return true } // Check we''re NOT on WWAN return !isOnWWAN(flags) } // MARK: - *** Private methods *** private var isRunningOnDevice: Bool = { #if (arch(i386) || arch(x86_64)) && os(iOS) return false #else return true #endif }() private var notifierRunning = false private var reachabilityRef: SCNetworkReachability? private let reachabilitySerialQueue = dispatch_queue_create("uk.co.ashleymills.reachability", DISPATCH_QUEUE_SERIAL) private func reachabilityChanged(flags: SCNetworkReachabilityFlags) { guard previousFlags != flags else { return } if isReachableWithFlags(flags) { if let block = whenReachable { block(self) } } else { if let block = whenUnreachable { block(self) } } notificationCenter.postNotificationName(ReachabilityChangedNotification, object:self) previousFlags = flags } private func isReachableWithFlags(flags: SCNetworkReachabilityFlags) -> Bool { if !isReachable(flags) { return false } if isConnectionRequiredOrTransient(flags) { return false } if isRunningOnDevice { if isOnWWAN(flags) && !reachableOnWWAN { // We don''t want to connect when on 3G. return false } } return true } // WWAN may be available, but not active until a connection has been established. // WiFi may require a connection for VPN on Demand. private func isConnectionRequired() -> Bool { return connectionRequired() } private func connectionRequired() -> Bool { let flags = reachabilityFlags return isConnectionRequired(flags) } // Dynamic, on demand connection? private func isConnectionOnDemand() -> Bool { let flags = reachabilityFlags return isConnectionRequired(flags) && isConnectionOnTrafficOrDemand(flags) } // Is user intervention required? private func isInterventionRequired() -> Bool { let flags = reachabilityFlags return isConnectionRequired(flags) && isInterventionRequired(flags) } private func isOnWWAN(flags: SCNetworkReachabilityFlags) -> Bool { #if os(iOS) return flags.contains(.IsWWAN) #else return false #endif } private func isReachable(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.Reachable) } private func isConnectionRequired(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.ConnectionRequired) } private func isInterventionRequired(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.InterventionRequired) } private func isConnectionOnTraffic(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.ConnectionOnTraffic) } private func isConnectionOnDemand(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.ConnectionOnDemand) } func isConnectionOnTrafficOrDemand(flags: SCNetworkReachabilityFlags) -> Bool { return !flags.intersect([.ConnectionOnTraffic, .ConnectionOnDemand]).isEmpty } private func isTransientConnection(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.TransientConnection) } private func isLocalAddress(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.IsLocalAddress) } private func isDirect(flags: SCNetworkReachabilityFlags) -> Bool { return flags.contains(.IsDirect) } private func isConnectionRequiredOrTransient(flags: SCNetworkReachabilityFlags) -> Bool { let testcase:SCNetworkReachabilityFlags = [.ConnectionRequired, .TransientConnection] return flags.intersect(testcase) == testcase } private var reachabilityFlags: SCNetworkReachabilityFlags { guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() } var flags = SCNetworkReachabilityFlags() let gotFlags = withUnsafeMutablePointer(&flags) { SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0)) } if gotFlags { return flags } else { return SCNetworkReachabilityFlags() } } override public var description: String { var W: String if isRunningOnDevice { W = isOnWWAN(reachabilityFlags) ? "W" : "-" } else { W = "X" } let R = isReachable(reachabilityFlags) ? "R" : "-" let c = isConnectionRequired(reachabilityFlags) ? "c" : "-" let t = isTransientConnection(reachabilityFlags) ? "t" : "-" let i = isInterventionRequired(reachabilityFlags) ? "i" : "-" let C = isConnectionOnTraffic(reachabilityFlags) ? "C" : "-" let D = isConnectionOnDemand(reachabilityFlags) ? "D" : "-" let l = isLocalAddress(reachabilityFlags) ? "l" : "-" let d = isDirect(reachabilityFlags) ? "d" : "-" return "/(W)/(R) /(c)/(t)/(i)/(C)/(D)/(l)/(d)" } deinit { stopNotifier() reachabilityRef = nil whenReachable = nil whenUnreachable = nil } }


Cree un nuevo archivo Swift dentro de su proyecto, Reachability.swift nombre Reachability.swift . Corta y pega el siguiente código para crear tu clase.

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(sizeofValue(zeroAddress)) zeroAddress.sin_family = sa_family_t(AF_INET) let defaultRouteReachability = withUnsafePointer(&zeroAddress) { SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0)) } var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0) if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false { return false } let isReachable = flags == .Reachable let needsConnection = flags == .ConnectionRequired return isReachable && !needsConnection } }

Puede verificar la conexión a Internet en cualquier parte de su proyecto utilizando este código:

if Reachability.isConnectedToNetwork() == true { println("Internet connection OK") } else { println("Internet connection FAILED") }

Si el usuario no está conectado a Internet, puede mostrarle un cuadro de diálogo de alerta para notificarlo.

if Reachability.isConnectedToNetwork() == true { println("Internet connection OK") } else { println("Internet connection FAILED") var alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK") alert.show() }

Explicación:

Estamos creando una clase pública reutilizable y un método que puede usarse en cualquier parte del proyecto para verificar la conectividad a Internet. Requerimos agregar marcos de Foundation y System Configuration.

En la clase pública Accesibilidad, el método isConnectedToNetwork() -> Bool { } devolverá un valor bool sobre la conectividad a Internet. Usamos un bucle if para realizar las acciones requeridas en el caso. Espero que esto sea suficiente. ¡Salud!


He comprobado la implementación de la clase de accesibilidad de Ashley Mill sin Cocoa Pods / Dependancy Manager. La idea es hacer que la dependencia de accesibilidad sea gratuita en el proyecto.

Xcode 7.2 - Swift 2.1

1) github.com/ashleymills/Reachability.swift . Descargar agregue la clase de accesibilidad al proyecto.

Nota: Al agregar, asegúrese de que la opción "copiar elementos si es necesario" esté marcada.

2) Crea una clase AppManager.swift. Esta clase servirá como clase de Modelo Público donde se agregarán métodos y datos públicos y se pueden utilizar en cualquier VC.

// AppManager.swift import UIKit import Foundation class AppManager: NSObject{ var delegate:AppManagerDelegate? = nil private var _useClosures:Bool = false private var reachability: Reachability? private var _isReachability:Bool = false private var _reachabiltyNetworkType :String? var isReachability:Bool { get {return _isReachability} } var reachabiltyNetworkType:String { get {return _reachabiltyNetworkType! } } // Create a shared instance of AppManager final class var sharedInstance : AppManager { struct Static { static var instance : AppManager? } if !(Static.instance != nil) { Static.instance = AppManager() } return Static.instance! } // Reachability Methods func initRechabilityMonitor() { print("initialize rechability...") do { let reachability = try Reachability.reachabilityForInternetConnection() self.reachability = reachability } catch ReachabilityError.FailedToCreateWithAddress(let address) { print("Unable to create/nReachability with address:/n/(address)") return } catch {} if (_useClosures) { reachability?.whenReachable = { reachability in self.notifyReachability(reachability) } reachability?.whenUnreachable = { reachability in self.notifyReachability(reachability) } } else { self.notifyReachability(reachability!) } do { try reachability?.startNotifier() } catch { print("unable to start notifier") return } } private func notifyReachability(reachability:Reachability) { if reachability.isReachable() { self._isReachability = true //Determine Network Type if reachability.isReachableViaWiFi() { self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.WIFI_NETWORK.rawValue } else { self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.WWAN_NETWORK.rawValue } } else { self._isReachability = false self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.OTHER.rawValue } NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name: ReachabilityChangedNotification, object: reachability) } func reachabilityChanged(note: NSNotification) { let reachability = note.object as! Reachability dispatch_async(dispatch_get_main_queue()) { if (self._useClosures) { self.reachability?.whenReachable = { reachability in self.notifyReachability(reachability) } self.reachability?.whenUnreachable = { reachability in self.notifyReachability(reachability) } } else { self.notifyReachability(reachability) } self.delegate?.reachabilityStatusChangeHandler(reachability) } } deinit { reachability?.stopNotifier() if (!_useClosures) { NSNotificationCenter.defaultCenter().removeObserver(self, name: ReachabilityChangedNotification, object: nil) } } }

3) Hacer una clase de delegado. Utilizo el método delegado para notificar el estado de conectividad.

// Protocols.swift import Foundation @objc protocol AppManagerDelegate:NSObjectProtocol { func reachabilityStatusChangeHandler(reachability:Reachability) }

4) Hacer la clase padre de UIViewController (método de herencia). La clase padre tiene métodos accesibles para todos los VC secundarios.

// UIappViewController.swift import UIKit class UIappViewController: UIViewController,AppManagerDelegate { var manager:AppManager = AppManager.sharedInstance override func viewDidLoad() { super.viewDidLoad() manager.delegate = self } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func reachabilityStatusChangeHandler(reachability: Reachability) { if reachability.isReachable() { print("isReachable") } else { print("notReachable") } } }

5) Inicie el Monitoreo de conectividad a Internet en tiempo real en AppDelegate.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { AppManager.sharedInstance.initRechabilityMonitor() return true }

6) He agregado una AppReference de Swift File Name para almacenar valores de enumeración constantes.

// AppReference.swift import Foundation enum CONNECTION_NETWORK_TYPE : String { case WIFI_NETWORK = "Wifi" case WWAN_NETWORK = "Cellular" case OTHER = "Other" }

7) En ViewController (por ejemplo, desea llamar a una API solo si la red está disponible)

// ViewController.swift import UIKit class ViewController: UIappViewController { var reachability:Reachability? override func viewDidLoad() { super.viewDidLoad() manager.delegate = self if(AppManager.sharedInstance.isReachability) { print("net available") //call API from here. } else { dispatch_async(dispatch_get_main_queue()) { print("net not available") //Show Alert } } //Determine Network Type if(AppManager.sharedInstance.reachabiltyNetworkType == "Wifi") { print(".Wifi") } else if (AppManager.sharedInstance.reachabiltyNetworkType == "Cellular") { print(".Cellular") } else { dispatch_async(dispatch_get_main_queue()) { print("Network not reachable") } } } override func viewWillAppear(animated: Bool) { } override func didReceiveMemoryWarning() { } }

La muestra se puede descargar en https://github.com/alvinreuben/Reachability-Sample

Actualizado a Swift 3.1- https://github.com/alvinvgeorge/Reachability-UpgradedToSwift3


Para resolver el problema de 4G mencionado en los comentarios, he utilizado la implementación de accesibilidad @AshleyMills como referencia y reescribí la Accesibilidad para Swift 3.1:

actualizado: Xcode 10.1 • Swift 4 o posterior

Archivo Reachability.swift

import Foundation import SystemConfiguration class Reachability { var hostname: String? var isRunning = false var isReachableOnWWAN: Bool var reachability: SCNetworkReachability? var reachabilityFlags = SCNetworkReachabilityFlags() let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue") init(hostname: String) throws { guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else { throw Network.Error.failedToCreateWith(hostname) } self.reachability = reachability self.hostname = hostname isReachableOnWWAN = true try start() } init() throws { var zeroAddress = sockaddr_in() zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size) zeroAddress.sin_family = sa_family_t(AF_INET) guard let reachability = withUnsafePointer(to: &zeroAddress, { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { SCNetworkReachabilityCreateWithAddress(nil, $0) } }) else { throw Network.Error.failedToInitializeWith(zeroAddress) } self.reachability = reachability isReachableOnWWAN = true try start() } var status: Network.Status { return !isConnectedToNetwork ? .unreachable : isReachableViaWiFi ? .wifi : isRunningOnDevice ? .wwan : .unreachable } var isRunningOnDevice: Bool = { #if targetEnvironment(simulator) return false #else return true #endif }() deinit { stop() } }

extension Reachability { func start() throws { guard let reachability = reachability, !isRunning else { return } var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque() guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop() throw Network.Error.failedToSetCallout } guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop() throw Network.Error.failedToSetDispatchQueue } reachabilitySerialQueue.async { self.flagsChanged() } isRunning = true } func stop() { defer { isRunning = false } guard let reachability = reachability else { return } SCNetworkReachabilitySetCallback(reachability, nil, nil) SCNetworkReachabilitySetDispatchQueue(reachability, nil) self.reachability = nil } var isConnectedToNetwork: Bool { return isReachable && !isConnectionRequiredAndTransientConnection && !(isRunningOnDevice && isWWAN && !isReachableOnWWAN) } var isReachableViaWiFi: Bool { return isReachable && isRunningOnDevice && !isWWAN } /// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection. var flags: SCNetworkReachabilityFlags? { guard let reachability = reachability else { return nil } var flags = SCNetworkReachabilityFlags() return withUnsafeMutablePointer(to: &flags) { SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0)) } ? flags : nil } /// compares the current flags with the previous flags and if changed posts a flagsChanged notification func flagsChanged() { guard let flags = flags, flags != reachabilityFlags else { return } reachabilityFlags = flags NotificationCenter.default.post(name: .flagsChanged, object: self) } /// The specified node name or address can be reached via a transient connection, such as PPP. var transientConnection: Bool { return flags?.contains(.transientConnection) == true } /// The specified node name or address can be reached using the current network configuration. var isReachable: Bool { return flags?.contains(.reachable) == true } /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set. var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true } /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection. var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true } /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true } /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection. var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true } /// The specified node name or address is one that is associated with a network interface on the current system. var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true } /// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system. var isDirect: Bool { return flags?.contains(.isDirect) == true } /// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS. var isWWAN: Bool { return flags?.contains(.isWWAN) == true } /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set /// The specified node name or address can be reached via a transient connection, such as PPP. var isConnectionRequiredAndTransientConnection: Bool { return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true } }

func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) { guard let info = info else { return } DispatchQueue.main.async { Unmanaged<Reachability> .fromOpaque(info) .takeUnretainedValue() .flagsChanged() } }

extension Notification.Name { static let flagsChanged = Notification.Name("FlagsChanged") }

struct Network { static var reachability: Reachability! enum Status: String { case unreachable, wifi, wwan } enum Error: Swift.Error { case failedToSetCallout case failedToSetDispatchQueue case failedToCreateWith(String) case failedToInitializeWith(sockaddr_in) } }

Uso

Inicialícelo en su método AppDelegate.swift didFinishLaunchingWithOptions y maneje cualquier error que pueda ocurrir:

import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { do { try Network.reachability = Reachability(hostname: "www.google.com") } catch { switch error as? Network.Error { case let .failedToCreateWith(hostname)?: print("Network error:/nFailed to create reachability object With host named:", hostname) case let .failedToInitializeWith(address)?: print("Network error:/nFailed to initialize reachability object With address:", address) case .failedToSetCallout?: print("Network error:/nFailed to set callout") case .failedToSetDispatchQueue?: print("Network error:/nFailed to set DispatchQueue") case .none: print(error) } } return true } }

Y una muestra de controlador de vista:

import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default .addObserver(self, selector: #selector(statusManager), name: .flagsChanged, object: nil) updateUserInterface() } func updateUserInterface() { switch Network.reachability.status { case .unreachable: view.backgroundColor = .red case .wwan: view.backgroundColor = .yellow case .wifi: view.backgroundColor = .green } print("Reachability Summary") print("Status:", Network.reachability.status) print("HostName:", Network.reachability.hostname ?? "nil") print("Reachable:", Network.reachability.isReachable) print("Wifi:", Network.reachability.isReachableViaWiFi) } @objc func statusManager(_ notification: Notification) { updateUserInterface() } }

Proyecto de muestra


Si alguien ya está usando Alamofire entonces:

struct Connectivity { static let sharedInstance = NetworkReachabilityManager()! static var isConnectedToInternet:Bool { return self.sharedInstance.isReachable } }

Uso:

if Connectivity.isConnectedToInternet { print("Connected") } else { print("No Internet") }


Para Swift 3, Swift 4 (trabajando con celular y Wi-Fi):

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 } /* Only Working for WIFI let isReachable = flags == .reachable let needsConnection = flags == .connectionRequired return isReachable && !needsConnection */ // Working for Cellular and WIFI let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 let ret = (isReachable && !needsConnection) return ret } }

Uso:

if Reachability.isConnectedToNetwork(){ print("Internet Connection Available!") }else{ print("Internet Connection not Available!") }


struct Connectivity { static let sharedInstance = NetworkReachabilityManager()! static var isConnectedToInternet:Bool { return self.sharedInstance.isReachable } }

Ahora llámalo

if Connectivity.isConnectedToInternet{ call_your_methods_here() }else{ show_alert_for_noInternet() }