web-dev-qa-db-de.com

Erkennen von Netzwerkkonnektivitätsänderungen mithilfe von Erreichbarkeit, NS-Benachrichtigung und Network Link Conditioner in Swift

Ich versuche, Netzwerkkonnektivität Erkennung in meine App zu integrieren, aber es scheint, als habe ich irgendwo einen Fehler gemacht, da meine Netzwerkänderungen nicht in der Konsole erkannt/ausgedruckt werden.

Wie in dem Post erwähnt, verwende ich derzeit folgende Klassen und Werkzeuge für den Job:

  1. Erreichbarkeit {.h, .m} 
  2. NSNotificationCenter
  3. Network Link Conditioner

Code

In der AppDelegate.Swift habe ich die NSNotificationCenter so eingerichtet, dass sie Änderungen erkennt:

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 derselben Klasse AppDelegate habe ich auch diese Funktion erstellt, die bei jeder Änderung ausgelöst wird: 

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")
    }
}

Bei der Verwendung des Network Link Conditioner zum Bearbeiten und Simulieren von Änderungen der Bedingungen konnte ich jedoch keine dieser Änderungen in der Konsole sehen. Jede Hilfe wäre anschwellen!

21
iamktothed

Sie müssen ein Erreichbarkeitsobjekt erstellen, bevor Sie Benachrichtigungen erhalten können. Rufen Sie außerdem unbedingt die Methode startNotifier() für das von Ihnen erstellte Erreichbarkeitsobjekt auf. Dies wäre ein Beispiel dafür, wie Sie dies innerhalb Ihres Anwendungsdelegierten tun:

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();
    }

    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")
        }
    }
}

Ich empfehle Ihnen, sich die Dokumentation zu NSNotificationCenter und NSNotification anzusehen. Auf diese Weise werden Sie mit der Verwendung von Benachrichtigungen beim nächsten Mal besser vertraut.

Swift 3

NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil)
let reachability: Reachability = Reachability.forInternetConnection()
reachability.startNotifier()
32
A. R. Younce

Anstatt den AppDelegate.Swift mit Observer-Callbacks zu verschmutzen, würde ich empfehlen, Observer nur in die entsprechenden View-Controller aufzunehmen.

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
}

Beispiel eines ViewControllers:

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")
        }
    }
}
5
AndreasLukas

Aktualisiert für Swift 2.1 und XCode 7:

versuchen Sie es mit dieser Drittanbieter-Hochklassifizierten Erreichbarkeitsklasse

 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)
        }
    }
4
Sourabh Sharma

Antwort von A. R. Younce für Swift 2 aktualisiert:

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")
    }
}
3
EPage_Ed

Für Swift 4 entsprechend @ Hardik.T aktualisiert

1. Importieren Sie Reachability.Swift-Datei von https://github.com/ashleymills/Reachability.Swift/archive/master.Zip in Ihr XCode-Projekt

2. Neue Swift-Klasse erstellen: 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. Verwenden Sie es in Ihrer AppDelegate-Datei:

func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    ConnectionManager.sharedInstance.observeReachability()
    return true
}
3
AnthonyR

Basierend auf diese Open-Source-Lösung 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
  }
}
2
gbk

Swift 2.0 - Netzwerk mit Erreichbarkeit prüfen, NS-Benachrichtigung  

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
}

Deklarieren Sie die Variable networkStatus

var networkStatus : Reachability.NetworkStatus!

funktion 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  
}
1

1) Installieren Sie den Pod oder fügen Sie ReachabilitySwift in Ihr Projekt ein

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")
        }
    }
1
Hardik Thakkar