You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合NWPathMonitor与Alamofire实现全局网络校验及请求拦截逻辑

实现方案

这里提供两种落地成本低、兼容性强的方案,你可以根据现有项目的代码存量选择:


方案1:统一请求入口加前置校验(推荐新项目使用)

把所有业务层的请求调用收敛到NetworkManager的统一公共方法里,在方法最开始插入网络状态校验逻辑,后续所有新增请求自动复用逻辑,无需重复写判断:

import Alamofire

class NetworkManager {
    static let shared = NetworkManager()
    private init() {}
    
    // 所有业务请求必须走这个统一入口
    func request(
        url: String,
        method: HTTPMethod,
        parameters: Parameters? = nil,
        headers: HTTPHeaders? = nil,
        success: @escaping (Any) -> Void,
        failure: @escaping (Error) -> Void
    ) {
        // 前置校验网络状态
        guard MonitorManager.shared.isReachable else {
            // 弹全局无网络提示
            showNoNetworkAlert()
            // 返回标准无网络错误,业务层可统一识别处理
            let noNetworkError = NSError(
                domain: NSURLErrorDomain,
                code: NSURLErrorNotConnectedToInternet,
                userInfo: [NSLocalizedDescriptionKey: "当前无网络连接,请检查网络设置"]
            )
            failure(noNetworkError)
            return
        }
        
        // 网络正常才发起实际请求
        AF.request(url, method: method, parameters: parameters, headers: headers)
            .validate()
            .responseJSON { response in
                switch response.result {
                case .success(let value):
                    success(value)
                case .failure(let error):
                    failure(error)
                }
            }
    }
    
    // 全局无网络弹窗
    private func showNoNetworkAlert() {
        DispatchQueue.main.async { // 确保UI操作在主线程执行
            guard let topVC = UIApplication.shared.keyWindow?.rootViewController?.topMostVC() else { return }
            let alert = UIAlertController(title: "网络异常", message: "当前无可用网络,请检查后重试", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            topVC.present(alert, animated: true)
        }
    }
}

// 工具扩展:获取当前顶层控制器用于弹窗
extension UIViewController {
    func topMostVC() -> UIViewController {
        if let presentedVC = self.presentedViewController {
            return presentedVC.topMostVC()
        }
        if let navVC = self as? UINavigationController {
            return navVC.visibleViewController?.topMostVC() ?? navVC
        }
        if let tabVC = self as? UITabBarController {
            return tabVC.selectedViewController?.topMostVC() ?? tabVC
        }
        return self
    }
}

这个方案的优势是逻辑可控,后续要加公共参数、签名、统一响应解析等逻辑都可以直接在入口方法里扩展。


方案2:用Alamofire拦截器实现底层拦截(适合存量请求多的老项目)

如果你的项目已经有大量零散的Alamofire请求,不想逐个改调用入口,可以用Alamofire自带的RequestInterceptor机制,在请求发出的底层统一拦截校验:

// 自定义网络拦截器
class NetworkCheckInterceptor: RequestInterceptor {
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        guard MonitorManager.shared.isReachable else {
            // 无网络直接返回错误,不会发起实际网络请求
            let noNetworkError = NSError(
                domain: NSURLErrorDomain,
                code: NSURLErrorNotConnectedToInternet,
                userInfo: [NSLocalizedDescriptionKey: "当前无网络连接,请检查网络设置"]
            )
            // 弹全局提示
            DispatchQueue.main.async {
                NetworkManager.shared.showNoNetworkAlert()
            }
            completion(.failure(noNetworkError))
            return
        }
        // 网络正常放行请求
        completion(.success(urlRequest))
    }
}

然后在NetworkManager里初始化绑定了拦截器的Alamofire Session,替换掉默认的全局AF实例:

class NetworkManager {
    static let shared = NetworkManager()
    // 自定义Session,绑定拦截器
    private let session: Session = {
        let config = URLSessionConfiguration.af.default
        let interceptor = NetworkCheckInterceptor()
        return Session(configuration: config, interceptor: interceptor)
    }()
    private init() {}
    
    // 后续所有请求都用这个session发起即可自动触发网络校验
    func request(/* 请求参数 */) {
        session.request(/* 传参 */).responseJSON { /* 处理响应 */ }
    }
}

注意事项

  • 如果有离线缓存类的特殊请求,可以加白名单机制,无网络时跳过校验直接走本地缓存逻辑
  • MonitorManager的网络状态建议用系统NWPathMonitor或Alamofire自带的NetworkReachabilityManager实现,确保状态实时性
  • 所有UI相关操作(弹窗)必须切换到主队列执行,避免子线程调用UI导致崩溃

内容的提问来源于stack exchange,提问作者Dogan Altinbas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 18:06:03