Alamofire - NetworkReachabilityManager doesn't work with .notReachable - ios

I have an issue with NetworkReachabilityManager from Alamofire. I tried to test the connection with this example code:
override func viewDidLoad() {
super.viewDidLoad()
let manager = NetworkReachabilityManager(host: "www.apple.com")
manager?.listener = { status in
switch status {
case .notReachable:
print("network connection status - lost")
case .reachable(NetworkReachabilityManager.ConnectionType.ethernetOrWiFi):
print("network connection status - ethernet/WiFI")
case .reachable(NetworkReachabilityManager.ConnectionType.wwan):
print("network connection status - wwan")
default:
break
}
}
manager?.startListening()
}
When I tried to turn the wifi off and I received only blank response. No response like such as "network connection status - lost".
But when I tried to turn on the wifi and I received the result "network connection status - ethernet/WiFI" in which is good response. Any idea what is wrong with .notReachable? Any suggestion appreciated.

According to Alamofire "Make sure to remember to retain the manager" so create a manager like this
class A: UIViewController{
let manager = NetworkReachabilityManager(host: "www.apple.com")
override func viewDidLoad() {
super.viewDidLoad()
// before start listening you can check
if (manager?.isReachableOnEthernetOrWiFi == true)
{
print("internet is available")
}
else
{
print("internet is not available")
}
manager?.startListening()
manager?.listener = { status in
switch status {
case .notReachable:
print("network connection status - lost")
case .reachable(NetworkReachabilityManager.ConnectionType.ethernetOrWiFi):
print("network connection status - ethernet/WiFI")
case .reachable(NetworkReachabilityManager.ConnectionType.wwan):
print("network connection status - wwan")
default:
break
}
}
}
}

Related

update the Viewcontroller based on Network Availblilty in swift

I am new to ios development, i have to check the internet network based on that i will show the view controllers, i used this code for test the network.
class Connectivity {
class func isConnectedToInternet() ->Bool {
return NetworkReachabilityManager()!.isReachable
}
}
if Connectivity.isConnectedToInternet() {
print("Yes! internet is available.")
// do some tasks..
}
else {
}
with this code i am getting network network status, my aim is when the application launch time if don't have network show the default page, if enable the network automatically it will show the main page please help me.
try this code
let reachability = Reachability()!
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged(note:)), name: .reachabilityChanged, object: reachability)
do{
try reachability.startNotifier()
}catch{
print("could not start reachability notifier")
}
#objc func reachabilityChanged(note: Notification) {
let reachability = note.object as! Reachability
switch reachability.connection {
case .wifi:
print("Reachable via WiFi")
case .cellular:
print("Reachable via Cellular")
case .none:
print("Network not reachable")
}
}

How to detect if iOS Wifi hardware is ON swift 3

I'm trying to check if the WIFI hardware is on. I don't care if it is connected to internet or not. I just need to know if in the config the wifi is on. I need this because I will be using the GPS and I want to assure that I get the best accuracy.
enum ReachabilityType: CustomStringConvertible {
case wwan
case wiFi
var description: String {
switch self {
case .wwan: return "WWAN"
case .wiFi: return "WiFi"
}
}
}
I would suggest to use this Pod: https://github.com/ashleymills/Reachability.swift you can check whether you're connected via wifi or cellular or not connected
if reachability.isReachable {
if reachability.isReachableViaWiFi {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
} else {
print("Network not reachable")
}

How do I use this code in a singleton in swift?

I have this code that I found here. Now I would like to know how to use it in a singleton. My understanding is if I use this code in a singleton I will be noticed if there is a change in the network status.
func startNetworkReachabilityObserver() {
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
reachabilityManager?.listener = { status in
switch status {
case .NotReachable:
print("The network is not reachable")
case .Unknown :
print("It is unknown whether the network is reachable")
case .Reachable(.EthernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .Reachable(.WWAN):
print("The network is reachable over the WWAN connection")
}
}
// start listening
reachabilityManager?.startListening()
}
Using a singleton is working as I long as you keep a reference of reachabilityManager
class NetworkStatus {
static let sharedInstance = NetworkStatus()
private init() {}
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
}
}
reachabilityManager?.startListening()
}
}
So you can use it like this:
let networkStatus = NetworkStatus.sharedInstance
override func awakeFromNib() {
super.awakeFromNib()
networkStatus.startNetworkReachabilityObserver()
}
You will be notified of any change in your network status.
Hoist the variable into the class as a property. Add a static shared property to make your class a singleton.
class ReachabilityManager {
private let networkReachabilityManager = NetworkReachabilityManager()
static let shared = ReachabilityManager()
private override init () {
super.init()
networkReachabilityManager?.listener = { status in
//Post Notifications here
}
}
}
func startListening() {
networkReachabilityManager.startListening()
}
}
The static properties are lazy by default so when you call ReachabilityManager.shared.startListening() it will instantiate the singleton the first time and subsequent calls use the existing shared instance.

NEVPNManager check is connected after restart the app?

I coding a VPN tool, using the NetworkExtension framework. I can connect IPSec through NEVPNManager.sharedManager, and can grab the notification when VPN connect status changed. But when I kill the app, and reopen it, the NEVPNManager.Connect.Status always Zero, than means can't display the correct connect state. How to solve it?
William Sterling comment does make sense, & it works for me,
Before adding observer for NEVPNStatusDidChange load preferences for VPN Manager object like bellow,
override func viewDidLoad() {
super.viewDidLoad()
self.vpnManager.loadFromPreferences { (error) in
if error != nil {
print(error.debugDescription)
}
else{
print("No error from loading VPN viewDidLoad")
}
}
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.VPNStatusDidChange(_:)), name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
}
Try this:
func viewDidLoad() {
// Register to be notified of changes in the status. These notifications only work when app is in foreground.
notificationObserver = NSNotificationCenter.defaultCenter().addObserverForName(NEVPNStatusDidChangeNotification, object: nil , queue: nil) {
notification in
print("received NEVPNStatusDidChangeNotification")
let nevpnconn = notification.object as! NEVPNConnection
let status = nevpnconn.status
self.checkNEStatus(status)
}
}
func checkNEStatus( status:NEVPNStatus ) {
switch status {
case NEVPNStatus.Invalid:
print("NEVPNConnection: Invalid")
case NEVPNStatus.Disconnected:
print("NEVPNConnection: Disconnected")
case NEVPNStatus.Connecting:
print("NEVPNConnection: Connecting")
case NEVPNStatus.Connected:
print("NEVPNConnection: Connected")
case NEVPNStatus.Reasserting:
print("NEVPNConnection: Reasserting")
case NEVPNStatus.Disconnecting:
print("NEVPNConnection: Disconnecting")
}
}
The above code should generate the following messages when running the app with VPN already connected:
checkNEStatus: NEVPNConnection: Invalid
viewDidLoad: received NEVPNStatusDidChangeNotification
checkNEStatus: NEVPNConnection: Connected

How to use NetworkReachabilityManager in Alamofire

I want functionality similar to AFNetworking in Objective-C with Alamofire NetworkReachabilityManager in Swift:
//Reachability detection
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN: {
[self LoadNoInternetView:NO];
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi: {
[self LoadNoInternetView:NO];
break;
}
case AFNetworkReachabilityStatusNotReachable: {
break;
}
default: {
break;
}
}
}];
I am currently using the listener to know the status changes with network
let net = NetworkReachabilityManager()
net?.startListening()
Can someone describe how to support those use cases?
NetworkManager Class
class NetworkManager {
//shared instance
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
}
}
// start listening
reachabilityManager?.startListening()
}
}
Start Network Reachability Observer
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// add network reachability observer on app start
NetworkManager.shared.startNetworkReachabilityObserver()
return true
}
}
I found the answer myself i.e by just writing a listener with closure as mentioned below:
let net = NetworkReachabilityManager()
net?.listener = { status in
if net?.isReachable ?? false {
switch status {
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
}
}
net?.startListening()
Here's my implementation. I use it in a singleton. Remember to hold on to the reachability manager reference.
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")
func listenForReachability() {
self.reachabilityManager?.listener = { status in
print("Network Status Changed: \(status)")
switch status {
case .NotReachable:
//Show error state
case .Reachable(_), .Unknown:
//Hide error state
}
}
self.reachabilityManager?.startListening()
}
SWIFT 5
NetworkState Structure
import Foundation
import Alamofire
struct NetworkState {
var isInternetAvailable:Bool
{
return NetworkReachabilityManager()!.isReachable
}
}
Use: -
if (NetworkState().isInternetAvailable) {
// Your code here
}
Using a singleton is working as I long as you keep a reference of reachabilityManager
class NetworkStatus {
static let sharedInstance = NetworkStatus()
private init() {}
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
}
}
reachabilityManager?.startListening()
}
So you can use it like this anywhere in your app:
let networkStatus = NetworkStatus.sharedInstance
override func awakeFromNib() {
super.awakeFromNib()
networkStatus.startNetworkReachabilityObserver()
}
You will be notified of any change in your network status.
Just for icing on the cake this is a very good animation to show on your internet connection loss.
Swift 5:
No need for listener object . Just we need to call the closure :
struct Network {
let manager = Alamofire.NetworkReachabilityManager()
func state() {
manager?.startListening { status in
switch status {
case .notReachable :
print("not reachable")
case .reachable(.cellular) :
print("cellular")
case .reachable(.ethernetOrWiFi) :
print("ethernetOrWiFi")
default :
print("unknown")
}
}
}
}
You can start using this function like :
Network().state()
Apple says to use a struct instead of a class when you can. So here's my version of #rmooney and #Ammad 's answers, but using a struct instead of a class. Additionally, instead of using a method or function, I am using a computed property and I got that idea from this Medium post by #Abhimuralidharan. I'm just putting both the idea of using a struct instead of a class (so you don't have to have a singleton) and using a computed property instead of a method call together in one solution.
Here's the struct NetworkState:
import Foundation
import Alamofire
struct NetworkState {
var isConnected: Bool {
// isReachable checks for wwan, ethernet, and wifi, if
// you only want 1 or 2 of these, the change the .isReachable
// at the end to one of the other options.
return NetworkReachabilityManager(host: www.apple.com)!.isReachable
}
}
Here is how you use it in any of your code:
if NetworkState().isConnected {
// do your is Connected stuff here
}
To create NetworkManager Class as follows (For SWIFT 5)
import UIKit
import Alamofire
class NetworkManager {
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.startListening(onUpdatePerforming: { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.cellular):
print("The network is reachable over the cellular connection")
}
})
}
}
And the usage will be like
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// add network reachability observer on app start
NetworkManager.shared.startNetworkReachabilityObserver()
return true
}
}
Alamofire 5 and above
import Alamofire
// MARK: NetworkReachability
final class NetworkReachability {
static let shared = NetworkReachability()
private let reachability = NetworkReachabilityManager(host: "www.apple.com")!
typealias NetworkReachabilityStatus = NetworkReachabilityManager.NetworkReachabilityStatus
private init() {}
/// Start observing reachability changes
func startListening() {
reachability.startListening { [weak self] status in
switch status {
case .notReachable:
self?.updateReachabilityStatus(.notReachable)
case .reachable(let connection):
self?.updateReachabilityStatus(.reachable(connection))
case .unknown:
break
}
}
}
/// Stop observing reachability changes
func stopListening() {
reachability.stopListening()
}
/// Updated ReachabilityStatus status based on connectivity status
///
/// - Parameter status: `NetworkReachabilityStatus` enum containing reachability status
private func updateReachabilityStatus(_ status: NetworkReachabilityStatus) {
switch status {
case .notReachable:
print("Internet not available")
case .reachable(.ethernetOrWiFi), .reachable(.cellular):
print("Internet available")
case .unknown:
break
}
}
/// returns current reachability status
var isReachable: Bool {
return reachability.isReachable
}
/// returns if connected via cellular
var isConnectedViaCellular: Bool {
return reachability.isReachableOnCellular
}
/// returns if connected via cellular
var isConnectedViaWiFi: Bool {
return reachability.isReachableOnEthernetOrWiFi
}
deinit {
stopListening()
}
}
How to use:
Call NetworkReachability.shared.startListening() from AppDelegate to start listening for reachability changes
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NetworkReachability.shared.startListening()
// window and rootviewcontroller setup code
return true
}
}
Solution for swift 4* + swift 5* and Alamofire 4.5+
CREATE a NetworkReachabilityManager class from Alamofire and
configure the checkNetwork() method
import Alamofire
class Connectivity {
class func checkNetwork() ->Bool {
return NetworkReachabilityManager()!.isReachable
}
}
USAGE
switch Connectivity.checkNetwork() {
case true:
print("network available")
//perform task
case false:
print("no network")
}
Just slight Improvement in the Alamofire 5
class NetworkManager {
//shared instance
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.startListening { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.cellular):
print("The network is reachable over the cellular connection")
}
}
}
}

Resources