Alamofire-网络监控

一、NetworkReachabilityManager使用

//AppDelegate
let networkManager = NetworkReachabilityManager(host: "www.apple.com")
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        /// 网络监控
        networkManager!.listener = {
            status in
            var message = ""
            
            switch status {
            case .unknown:
                message = "未知网络,请检查..."
            case .notReachable:
                message = "无法连接网络,请检查..."
            case .reachable(.wwan):
                message = "蜂窝移动网络,注意节省流量..."
            case .reachable(.ethernetOrWiFi):
                message = "WIFI-网络,使劲造吧..."
            }
            print("*******\(message)*******")
            let alertVC = UIAlertController(title: "网络状况提示", message: message, preferredStyle: .alert)
            alertVC.addAction(UIAlertAction(title: "我知道了", style: .default, handler: nil))
            self.window?.rootViewController?.present(alertVC, animated: true, completion: nil)
        }
        networkManager!.startListening()
        return true
    }
class ViewController: UIViewController {

    let urlString = "http://www.douban.com/j/app/radio/channels"
    let urlDownloadStr = "https://www.baidu.com"

    override func viewDidLoad() {
        super.viewDidLoad()
        Alamofire.request(urlString).response { (respose) in
            print("请求回调:\(respose)")
        }
    }
    
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        Alamofire.request(urlDownloadStr).response { (respose) in
            print("请求回调:\(respose)")
            if let error = respose.error as NSError?,error.code == -1009{
                
                print("无网络状态,请弹框...")
                let alertVC = UIAlertController(title: "无法连接网络", message: "确认网络连接无误,点击\"设置\"打开网络授权", preferredStyle: .alert)
                let settingAction = UIAlertAction(title: "设置", style: .default, handler: { (action) in
                    if let url = URL(string: UIApplication.openSettingsURLString),UIApplication.shared.canOpenURL(url) {
                        UIApplication.shared.open(url, options: [:], completionHandler: nil)
                    }
                    
                })
                alertVC.addAction(UIAlertAction(title: "我知道了", style: .destructive, handler: nil))
                alertVC.addAction(settingAction)

                UIApplication.shared.delegate?.window??.rootViewController?.present(alertVC, animated: true, completion: nil)
            }
        }
    }
}

二、源码解析

步骤一
  • 点击NetworkReachabilityManager(host: "www.apple.com")
  • SCNetworkReachabilityCreateWithName iOS系统方法
    public convenience init?(host: String) {
        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
        self.init(reachability: reachability)
    }
  • 点击self.init(reachability: reachability)
  • self.reachability = reachability
  • self.previousFlags = SCNetworkReachabilityFlags(rawValue: 1 << 30)
    private init(reachability: SCNetworkReachability) {
        self.reachability = reachability

        // Set the previous flags to an unreserved value to represent unknown status
        self.previousFlags = SCNetworkReachabilityFlags(rawValue: 1 << 30)
    }
  • SCNetworkReachability iOS系统类
public class SCNetworkReachability {
}
  • SCNetworkReachabilityFlags iOS系统结构体
public struct SCNetworkReachabilityFlags : OptionSet {

    public init(rawValue: UInt32)

    
    public static var transientConnection: SCNetworkReachabilityFlags { get }

    public static var reachable: SCNetworkReachabilityFlags { get }

    public static var connectionRequired: SCNetworkReachabilityFlags { get }

    public static var connectionOnTraffic: SCNetworkReachabilityFlags { get }

    public static var interventionRequired: SCNetworkReachabilityFlags { get }

    @available(iOS 3.0, *)
    public static var connectionOnDemand: SCNetworkReachabilityFlags { get }

    public static var isLocalAddress: SCNetworkReachabilityFlags { get }

    public static var isDirect: SCNetworkReachabilityFlags { get }

    @available(iOS 2.0, *)
    public static var isWWAN: SCNetworkReachabilityFlags { get }

    
    public static var connectionAutomatic: SCNetworkReachabilityFlags { get }
}
步骤二、保存闭包
  • 点击listener
  • open var listener: Listener?
  • public typealias Listener = (NetworkReachabilityStatus) -> Void
    public enum NetworkReachabilityStatus {
        case unknown
        case notReachable
        case reachable(ConnectionType)
    }

    public enum ConnectionType {
        case ethernetOrWiFi
        case wwan
    }
步骤三
  • 点击startListening()
    @discardableResult
    open func startListening() -> Bool {
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = Unmanaged.passUnretained(self).toOpaque()

        let callbackEnabled = SCNetworkReachabilitySetCallback(
            reachability,
            { (_, flags, info) in
                let reachability = Unmanaged.fromOpaque(info!).takeUnretainedValue()
                reachability.notifyListener(flags)
            },
            &context
        )

        let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)

        listenerQueue.async {
            guard let flags = self.flags else { return }
            self.notifyListener(flags)
        }

        return callbackEnabled && queueEnabled
    }
  • 点击self.notifyListener(flags)
  • listener?(networkReachabilityStatusForFlags(flags)) 执行闭包
    func notifyListener(_ flags: SCNetworkReachabilityFlags) {
        guard previousFlags != flags else { return }
        previousFlags = flags

        listener?(networkReachabilityStatusForFlags(flags))
    }
  • 点击networkReachabilityStatusForFlags
    func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {
        guard isNetworkReachable(with: flags) else { return .notReachable }

        var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi)

    #if os(iOS)
        if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) }
    #endif

        return networkStatus
    }

你可能感兴趣的:(Alamofire-网络监控)