如何在Alamofire中使用NetworkReachabilityManager

33

我希望在Swift中使用类似于Objective-C中AFNetworking的功能,并具备Alamofire NetworkReachabilityManager的特性:

//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;
        }
    }
}];

我目前正在使用监听器来了解网络状态的变化

let net = NetworkReachabilityManager()
net?.startListening()

有人能描述一下如何支持那些使用案例吗?

11个回答

39

NetworkManager 类

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

启动网络可达性观察器

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

reachabilityManager?.startListening() 你把它放错地方了,兄弟。:D - Marosdee Uma
7
我尝试过这个方法,但当你关闭 Wi-Fi 时监听器只会被调用一次,在你再次打开 Wi-Fi 时不会再次被调用。我看了几个地方的建议并试图持有一个对它的引用,例如,我尝试使用单例,但仍然遇到同样的问题。 - Jesus Rodriguez
@JesusAdolfoRodriguez - 我在模拟器中测试我的应用程序时遇到了完全相同的问题,但是当我将应用程序安装在设备上时,可达性管理器按照这里编写的方式工作。 - mattdedek
@mattdedek 谢谢您!我也遇到了同样的问题! - Juanbi Berretta
我们发现在某些使用代理服务器的企业网络中,使用可达性检测来测试主机会出现虚假的不可达情况。由于当时的网络是由第三方设置的,我们无法确定具体原因。因此,我们决定直接启动而不连接任何主机。 - RicardoDuarte

19

我自己找到了答案,即通过编写一个具有闭包的监听器,如下所示:

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

你能进一步解释一下你的答案吗?我的意思是,我应该在哪里添加这段代码?我需要为此创建单独的结构吗? - user3182143

16

这是我的实现方式。我将其用于单例中。记得保存可达性管理器的引用。

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

9

只要您保持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()
}

所以你可以在应用程序的任何地方像这样使用它:
let networkStatus = NetworkStatus.sharedInstance

override func awakeFromNib() {
    super.awakeFromNib()
    networkStatus.startNetworkReachabilityObserver()
}

您将收到网络状态变化的通知。 顺便提一下,这个是一个非常好的动画,可以在您的网络连接中断时显示。


9

SWIFT 5

网络状态结构体

import Foundation
import Alamofire

struct NetworkState {

    var isInternetAvailable:Bool
    {
        return NetworkReachabilityManager()!.isReachable
    }
}

使用方法:

  if (NetworkState().isInternetAvailable) {
        // Your code here
   }

1
这是否意味着我们不再需要使用 reachabilityManager?.listener,因为它会出现错误 Value of type 'NetworkReachabilityManager' has no member 'listener' - Mumtaz Hussain

6

Swift 5: 无需侦听器对象。只需要调用闭包:

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

您可以像这样开始使用此函数:

Network().state()

3
苹果建议您在可以使用时使用结构体,而不是类。因此,这是我基于@rmooney和@Ammad的答案版本,但使用结构体而不是类。此外,我使用计算属性而不是方法或函数,并从这篇Medium文章中得到了这个想法。文章作者是@Abhimuralidharan。我将使用结构体而不是单例的想法和使用计算属性而不是方法调用的想法放在一起,提供了一个解决方案。
下面是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
    }
}

以下是如何在任何代码中使用它的方法:

if NetworkState().isConnected {
    // do your is Connected stuff here
}

@user3182143 www.apple.com 只是一个例子,你应该放入你要检查的主机。在我的代码中,我放入了API所在的主机。 - jonathan3087

3
创建 NetworkManager 类,代码如下 (适用于 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")
                      }
        })
    }
}

使用方法将会是这样

@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(4.9.1):startListening仅返回bool。 - Abhishek Thapliyal
这是因为这段代码是为了兼容Alamofire 5而更改了API的这一部分。 - Heps

2

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

如何使用:

AppDelegate 中调用 NetworkReachability.shared.startListening() 开始监听网络连接状态的变化。

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

0

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

        }
     }
  }

 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接