使用Swift中的可达性,NSNotification和网络链接调节器检测网络连接变化

时间:2014-12-05 06:54:05

标签: ios swift nsnotificationcenter reachability

我正在尝试将网络连接检测功能整合到我的应用中,但似乎在线路的某处我犯了一个错误,因为我的网络更改未被检测/打印到控制台。

如帖子中所述,我目前正在使用以下课程和工具:

  1. 可达性{.h, .m}
  2. NSNotificationCenter
  3. 网络链接调节器
  4. 代码

    AppDelegate.Swift 中,我设置NSNotificationCenter来检测更改:

    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)
    

    }

    在同一个班级AppDelegate中,我还创建了此功能,以便在发生变化时触发:

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

    但是,当使用网络链接调节器来操作和模拟条件的变化时,我还没有能够看到控制台中反映出的任何变化。任何帮助都会膨胀!

11 个答案:

答案 0 :(得分:32)

您必须先创建一个可访问性对象 ,然后才能从中接收通知。另外,请务必在您创建的Reachability对象上调用startNotifier()方法。这将是一个如何在您的应用程序委托中执行此操作的示例:

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

我建议您查看NSNotificationCenterNSNotification的文档。通过这种方式,您可以更加熟悉下次出现此类通知时如何使用通知。

Swift 3

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

答案 1 :(得分:8)

根据@ Hardik.T

更新了Swift 4

1。在您的XCode项目中从https://github.com/ashleymills/Reachability.swift/archive/master.zip导入Reachability.swift个文件

2. :创建一个新的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。AppDelegate文件中使用它:

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

答案 2 :(得分:5)

我建议不要用观察者回调来污染SELECT * FROM `foobar` WHERE weight+0.0 <= '0,7 kg' ,而是建议只将观察者添加到相关的视图控制器中。

<强> SELECT * FROM `foobar` WHERE REPLACE(weight+0.0,',','.') <= REPLACE('0,7 kg',',','.')

AppDelegate.swift

ViewController示例:

AppDelegate.swift

答案 3 :(得分:4)

升级为快速2.1&amp; XCode 7:

尝试此第三方高度评价 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)
        }
    }

答案 4 :(得分:3)

更新了A. R. Younce对Swift 2的回答:

application_readable

答案 5 :(得分:1)

Swift 2.0 - 使用可访问性检查网络,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
}

声明networkStatus变量

var networkStatus : Reachability.NetworkStatus!

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  
}

答案 6 :(得分:1)

1)安装pod或在项目中添加 ReachabilitySwift

2)在 AppDelegate.swift

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

3)

{{1}}

答案 7 :(得分:0)

基于this open source solution 包装上课

快速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:

      }
    }
  }
}

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

答案 8 :(得分:0)

使用ReachabilitySwift框架,它是用闭包在Swift中重写的Apple可达性的替代方法

  1. 安装ReachabilitySwift Cocoapod

  2. 创建NetworkReachability包装类以观察可达性更改

    导入ReachabilitySwift

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

    }

    AppDelagete.Swift

    func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     NetworkReachability.shared.startNotifier()
     reahabilityObserver()
    }
    
    func reachabilityObserver() {
    
      NetworkReachability.shared.reachabilityObserver = { [weak self] status in
            switch status {
                case .connected:
                    print("Reachability: Network available ?")
                case .disconnected:
                    print("Reachability: Network unavailable ?")
            }
        }
    }
    

答案 9 :(得分:0)

Swift 5.0,Xcode 11.3

创建一个名为 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")
    }
 }


}

现在在您的appDelegate方法中。

NetworkListner.shared.startNWListner()

仔细阅读

在模拟器上

  • 在打开Internet时运行应用程序时,通知将 被触发
  • 然后关闭互联网-通知将被触发
  • 然后,如果您再次打开互联网,它将不会被触发

在模拟器上发现了这个问题。

在真实设备上效果很好,因此无需担心

答案 10 :(得分:0)

适用于 ios 12 及更高版本;

import Network

创建一个类

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

你需要的初始化类

 if #available(iOS 12.0, *) {
            let net = NetworkListener()
        }

你也可以监控特定的界面

let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)