Reputation: 1428
From iOS 12 you simply use NWPathMonitor
which is a line of code (example).
For historic purposes:
I'm trying to integrate network connectivity detection into my app, however it seems that somewhere along the line I have made a mistake as my network changes are not being detected/printed out into the console.
As mentioned in the post, I'm currently using these following classes and tools for the job:
{.h, .m}
NSNotificationCenter
Code
In the AppDelegate.Swift
, I've set up the NSNotificationCenter
to detect changes:
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)
}
In the same class AppDelegate
, I've also created this function to be triggered whenever there is a change:
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")
}
}
However, when using the Network Link Conditioner to manipulate and simulate changes in conditions, I haven't been able to see any of those changes reflected in the console.
Upvotes: 45
Views: 78450
Reputation: 12023
Using ReachabilitySwift framework which is a replacement for Apple's Reachability re-written in Swift with closures
Install ReachabilitySwift Cocoapod
Create NetworkReachability
wrapper class for observing the reachability changes
//
// NetworkReachability.swift
// NetworkMonitor
//
// Created by MANNAM on 02/03/23.
//
import Foundation
import Reachability
extension Notification.Name {
static let ReachabilityStatusChanged = Notification.Name("ReachabilityStatusChangedNotification")
}
//MARK: NetworkReachability
final class NetworkReachability {
enum ReachabilityStatus: Equatable {
case connected
case disconnected
}
static let shared = NetworkReachability()
private let reachability = try! Reachability()
var reachabilityObserver: ((ReachabilityStatus) -> Void)?
private(set) var reachabilityStatus: ReachabilityStatus = .connected
private init() {
setupReachability()
}
/// setup observer to detect reachability changes
private func setupReachability() {
let reachabilityStatusObserver: ((Reachability) -> ()) = { [unowned self] (reachability: Reachability) in
self.updateReachabilityStatus(reachability.connection)
}
reachability.whenReachable = reachabilityStatusObserver
reachability.whenUnreachable = reachabilityStatusObserver
}
/// Start observing reachability changes
func startNotifier() {
do {
try reachability.startNotifier()
} catch {
print(error.localizedDescription)
}
}
/// Stop observing reachability changes
func stopNotifier() {
reachability.stopNotifier()
}
/// Updated ReachabilityStatus status based on connectivity status
///
/// - Parameter status: Reachability.Connection enum containing reachability status
private func updateReachabilityStatus(_ status: Reachability.Connection) {
switch status {
case .unavailable, .none:
notifyReachabilityStatus(.disconnected)
case .cellular, .wifi:
notifyReachabilityStatus(.connected)
}
}
/// Notifies observers about reachability status change
///
/// - Parameter status: ReachabilityStatus enum indicating status eg. .connected/.disconnected
private func notifyReachabilityStatus(_ status: ReachabilityStatus) {
reachabilityStatus = status
reachabilityObserver?(status)
NotificationCenter.default.post(
name: Notification.Name.ReachabilityStatusChanged,
object: nil,
userInfo: ["ReachabilityStatus": status]
)
}
/// returns current reachability status
var isReachable: Bool {
return reachability.connection != .unavailable
}
/// returns if connected via cellular or wifi
var isConnectedViaCellularOrWifi: Bool {
return isConnectedViaCellular || isConnectedViaWiFi
}
/// returns if connected via cellular
var isConnectedViaCellular: Bool {
return reachability.connection == .cellular
}
/// returns if connected via cellular
var isConnectedViaWiFi: Bool {
return reachability.connection == .wifi
}
deinit {
stopNotifier()
}
}
in AppDelagete.Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NetworkReachability.shared.startNotifier()
reachabilityObserver()
return true
}
func reachabilityObserver() {
NetworkReachability.shared.reachabilityObserver = { [weak self] status in
switch status {
case .connected:
print("Reachability: Network available 😃")
case .disconnected:
print("Reachability: Network unavailable 😟")
}
}
}
Upvotes: 0
Reputation: 5953
for ios 12 and above;
import Network
create a class
@available(iOS 12.0, *)
class NetworkListener{
let monitor = NWPathMonitor()
init() {
monitor.pathUpdateHandler = { path in
if path.status == .satisfied {
print("network is now connected")
// Put your logic code
}else {
print("No connection.")
// Put your logic code
}
}
let queue = DispatchQueue.main // if your logic works on background edit accordingly
monitor.start(queue: queue)
}
}
init class where you need
if #available(iOS 12.0, *) {
let net = NetworkListener()
}
you can monitor specific interface also
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
Upvotes: 1
Reputation: 135
Swift 5.0 , Xcode 11.3
create a new file called NetworkListner.swift
class NetworkListner : NSObject {
static let shared = NetworkListner()
var reachabilityStatus: Reachability.Connection = .unavailable
let reachability = try! Reachability()
var isNetworkAvailable : Bool {
return reachabilityStatus != .unavailable
}
func startNWListner() {
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged(note:)), name: .reachabilityChanged, object: reachability)
reachability.whenReachable = { reachability in
if reachability.connection == .wifi {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
}
reachability.whenUnreachable = { _ in
print("Not reachable")
}
do {
try reachability.startNotifier()
} catch {
print("Unable to start 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 .unavailable:
print("Network not reachable")
case .none:
print("Network none")
}
}
}
Now in your appDelegate method.
NetworkListner.shared.startNWListner()
Read carefully
on simulator
Found this issue on simulator.
Works pretty well on real device so no worries
Upvotes: 0
Reputation: 3555
Updated for Swift 4 / Swift 5 according @Hardik.T
1. Import Reachability.swift
file from https://github.com/ashleymills/Reachability.swift/archive/master.zip in your XCode project
2. Create a new Swift class : 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
case .unavailable:
print("Network is unavailable.")
break
}
}
}
3. Use it in your AppDelegate
file :
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
ConnectionManager.sharedInstance.observeReachability()
return true
}
Upvotes: 24
Reputation: 1923
You must create a Reachability object before you can receive notifications from it. Also, be sure to call the startNotifier()
method on the Reachability object you create. This would be an example of how to do so inside of your application delegate:
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")
}
}
}
I recommend you take a look at the documentation for NSNotificationCenter and NSNotification. That way you'll be more familiar with how to work with notifications next time something like this comes up.
Swift 3
NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil)
let reachability: Reachability = Reachability.forInternetConnection()
reachability.startNotifier()
Upvotes: 39
Reputation: 11184
Based on this open source solution Wrapped to class
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:
}
}
}
}
In 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
}
}
Upvotes: 6
Reputation: 15991
1) Install pod or add ReachabilitySwift in your project
2) in 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")
}
}
Upvotes: 1
Reputation: 9074
Instead of polluting the AppDelegate.swift
with observer callbacks I would recommend adding observers only into the relevant view controllers.
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
}
Example of a 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")
}
}
}
Upvotes: 8
Reputation: 1441
Swift 2.0 - Check Network Using Reachability, 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
}
Declare networkStatus variable
var networkStatus : Reachability.NetworkStatus!
checkNetworkStatus() Function
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
}
Upvotes: 1
Reputation: 8322
Upadated for swift 2.1 & XCode 7:
try this third party Highly Rated Reachablity Class
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)
}
}
Upvotes: 4
Reputation: 1183
Updated A. R. Younce answer for 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")
}
}
Upvotes: 3