Swift.Alamofire的封装

作者: 王四猫 | 来源:发表于2018-09-11 15:16 被阅读66次

    实现功能:

    自动缓存,网络状态监听,无网络状态自动调用缓存数据.

    统一全局manager,一次设定baseURL与header.全局使用.

    优化调用方式,使网络请求更轻便,更直观.

    使用第三方库:

    Alamofire: 核心功能,网络请求.

    SwiftyJSON: 数据缓存时使用,方便地处理JSON数据.

    /建议配合使用MBProgressHud,但因为非必须,demo中去掉了./


    1.自动缓存

    在网络请求成功时调用,将数据存储.

    /// 进行数据缓存
        ///
        /// - Parameters:
        ///   - responseObject: 缓存数据
        ///   - request: 请求
        ///   - parameters: 参数
        public func cacheResponseObject(responseObject: AnyObject,
                                       request: URLRequest,
                                       parameters: Dictionary<String,Any>?){
            if !(responseObject is NSNull) {
                let directoryPath:String = cachePath
                ///如果没有目录,那么新建目录
                if !FileManager.default.fileExists(atPath: directoryPath, isDirectory: nil){
                    do {
                        try FileManager.default.createDirectory(atPath: directoryPath,
                                                                withIntermediateDirectories: true,
                                                                attributes: nil)
                    }catch let error {
                        print("create cache dir error: " + error.localizedDescription + "\n")
                        return
                    }
                }
                ///将get请求下的参数拼接到url上
                let absoluterURL = self.generateGETAbsoluteURL(url: (request.url?.absoluteString)!, parameters)
                ///对url进行md5加密
                let key = absoluterURL.md5()
                ///将加密过的url作为目录拼接到默认路径
                let path = directoryPath.appending(key)
                ///将请求数据转换成data
                let dict:AnyObject = responseObject
                var data:Data? = nil
                do{
                    try data = JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
                }catch{
                }
                ///将data存储到指定路径
                if data != nil{
                    let isOk = FileManager.default.createFile(atPath: path,
                                                              contents: data,
                                                              attributes: nil)
                    if isOk{
                        print("cache file ok for request: \(absoluterURL)\n")
                    }else{
                        print("cache file error for request: \(absoluterURL)\n")
                    }
                }
            }
        }
    

    2.网络状态监听.

      ///监听网络状态
        public func detectNetwork(netWorkStatus: @escaping ELNetworkStatus){
            let reachability = NetworkReachabilityManager()
            reachability?.startListening()
            reachability?.listener = { status in
                if reachability?.isReachable ?? false {
                    switch status {
                    case .notReachable:
                        ew_NetworkStatus = EWNetworkStatus.NotReachable
                    case .unknown:
                        ew_NetworkStatus = EWNetworkStatus.Unknown
                    case .reachable(.wwan):
                        ew_NetworkStatus = EWNetworkStatus.WWAN
                    case .reachable(.ethernetOrWiFi):
                        ew_NetworkStatus = EWNetworkStatus.WiFi
                    }
                }else{
                    ew_NetworkStatus = EWNetworkStatus.NotReachable
                }
                netWorkStatus(ew_NetworkStatus.rawValue)
            }
        }
    

    3.无网络时获取缓存数据

       ///从缓存中获取数据
        public func cahceResponseWithURL(url: String,paramters: Dictionary<String,Any>?) -> Any?{
            var cacheData:Any? = nil
            let directorPath = cachePath
            let absoluteURL = self.generateGETAbsoluteURL(url: url, paramters)
            ///使用md5进行加密
            let key = absoluteURL.md5()
            let path = directorPath.appending(key)
            let data:Data? = FileManager.default.contents(atPath: path)
            if data != nil{
                cacheData = data
                print("Read data from cache for url: \(url)\n")
            }
            return cacheData
        }
     ///解析缓存数据
        class func successResponse(responseData: Any,callback success: EWResponseSuccess){
            success(self.tryToParseData(responseData: responseData))
        }
        ///解析数据
        class func tryToParseData(responseData: Any) -> AnyObject {
            if responseData is Data{
                do{
                    let json =  try JSON(data: responseData as! Data)
                    return json as AnyObject
                }catch{
                    return responseData as AnyObject
                }
            }else{
                return responseData as AnyObject
            }
        }
    

    4.设定manager

    //获取alamofire.manager
       private lazy var manager: SessionManager = {
            let config:URLSessionConfiguration = URLSessionConfiguration.default
            let serverTrustPolicies: [String: ServerTrustPolicy] = [
                ///正式环境的证书配置,修改成自己项目的正式url
                "www.baidu.com": .pinCertificates(
                    certificates: ServerTrustPolicy.certificates(),
                    validateCertificateChain: true,
                    validateHost: true
                ),
                ///测试环境的证书配置,不验证证书,无脑通过
                "192.168.1.213:8002": .disableEvaluation,
                ]
            config.httpAdditionalHeaders = ew_httpHeaders
            config.timeoutIntervalForRequest = ew_timeout
            //根据config创建manager
            return SessionManager(configuration: config,
                                     delegate: SessionDelegate(),
                                     serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
        }()
    

    5.核心网络请求功能

    ///核心方法
        public func requestWith(url: String,
                               httpMethod: Int32,
                               params: Dictionary<String,Any>?,
                               success: @escaping EWResponseSuccess,
                               error: @escaping EWResponseFail){
            if (self.baseUrl() == nil) {
                if URL(string: url) == nil{
                    print("URLString无效")
                    return
                }
            } else {
                if URL(string: "\(self.baseUrl()!)\(url)" ) == nil{
                    print("URLString无效")
                    return
                }
            }
            let encodingUrl = encodingURL(path: url)
            let absolute = absoluteUrlWithPath(path: encodingUrl)
            let lastUrl = buildAPIString(path: absolute)
            //打印header进行调试.
            if let params = params{
                print("\(lastUrl)\nheader =\(String(describing: ew_httpHeaders))\nparams = \(params)")
            }else {
                print("\(lastUrl)\nheader =\(String(describing: ew_httpHeaders))")
            }
            //get
            if httpMethod == 0{
                //无网络状态获取缓存
                if ew_NetworkStatus.rawValue == EWNetworkStatus.NotReachable.rawValue
                    || ew_NetworkStatus.rawValue == EWNetworkStatus.Unknown.rawValue {
                    let response = self.cahceResponseWithURL(url: lastUrl,
                                                                     paramters: params)
                    if response != nil{
                        self.successResponse(responseData: response!, callback: success)
                    }else{
                        return
                    }
                }
                manager.request(lastUrl,
                                 method: .get,
                                 parameters: params,
                                 encoding: URLEncoding.default,
                                 headers: nil).responseJSON {
                                    (response) in
                                    switch response.result{
                                    case .success:
                                        if let value = response.result.value as? Dictionary<String,Any>{
                                            ///添加一些全部接口都有的一些状态判断
                                            if value["status"] as! Int == 1010 {
                                                error("登录超时,请重新登录" as AnyObject)
                                                _ = Keychain.clear()
                                                return
                                            }
                                            success(value as AnyObject)
                                            //缓存数据
                                            self.cacheResponseObject(responseObject: value as AnyObject,
                                                                     request: response.request!,
                                                                     parameters: nil)
                                        }
                                    case .failure(let err):
                                        error(err as AnyObject)
                                        debugPrint(err)
                                    }
                }
            }else{
                //post
                manager.request(lastUrl,
                                 method: .post,
                                 parameters: params!,
                                 encoding: JSONEncoding.default,
                                 headers: nil).responseJSON { (response) in
                                    switch response.result{
                                    case .success:
                                        ///添加一些全部接口都有的一些状态判断
                                        if let value = response.result.value as? Dictionary<String,Any> {
                                            if value["status"] as! Int == 1010 {
                                                error("登录超时,请重新登录" as AnyObject)
                                                _ = Keychain.clear()
                                                return
                                            }
                                            success(value as AnyObject)
                                        }
                                    case .failure(let err):
                                        error(err as AnyObject)
                                        debugPrint(error)
                                    }
                }
            }
        }
    

    6.添加请求方法

    
    extension EWNetworking{
        ///get请求demo
        public func getDataTest(id: String,
                           success: @escaping EWResponseSuccess,
                           failure: @escaping EWResponseFail){
            let path = "test"
            EWNetworking.ShareInstance.getWith(url: path, params: ["id": id], success: { (response) in
                guard let json = response as? [String:Any] else { return }
                ///保证接口调通, 否则返回错误信息
                guard json["status"] as! NSNumber == 1 else {
    //                MBProgressHud.showTextHudTips(message: json["msg"] as? String)
                    print(json["msg"])
                    failure(response)
                    return
                }
                guard let dict = json["obj"] as? [String:Any] else {
                    failure(NSError(domain: "转字典失败", code: 2000, userInfo: nil))
                    return
                }
                guard let dataArray = dict["data"] else {
                    failure(NSError(domain: "获取数组失败", code: 2000, userInfo: nil))
                    return
                }
                success(dataArray as AnyObject)
            }) { (error) in
                failure(error)
    //            MBProgressHud.showTextHudTips(message: "网络请求错误")
            }
        }
        ///post请求demo
        public func postDataTest(id: String,
                                    success: @escaping EWResponseSuccess,
                                    failure: @escaping EWResponseFail){
            let path = "v1/passport/register"
            EWNetworking.ShareInstance.postWith(url: path, params: ["id": id], success: { (response) in
                guard let json = response as? [String:Any] else { return }
                guard json["status"] as! NSNumber == 1 else {
    //                MBProgressHud.showTextHudTips(message: json["msg"] as? String)
                    print(json["msg"])
                    failure(response)
                    return
                }
                success(response as AnyObject)
            }) { (error) in
                failure(error)
    //            MBProgressHud.showTextHudTips(message: "网络请求错误")
            }
        }
    }
    

    7.调用请求demo

     func getDemo(){
            EWNetworking.ShareInstance.getDataTest(id: "1", success: { [weak self] (response) in
                guard let weakSelf = self else { return }
                guard let model = response as? [String] else { return }
                ///根据获取model来进行相应操作
            }) { (error) in
            }
        }
        func postDemo(){
            EWNetworking.ShareInstance.postDataTest(id: "1", success: { [weak self] (response) in
                guard let weakSelf = self else { return }
                guard let model = response as? [String] else { return }
                ///根据获取model来进行相应操作
            }) { (error) in
            }
        }
    

    demo地址:AlamofireEncapsulation

    网络请求是开发中非常非常核心的一部分,也是非常非常常用的一部分,所以优化我们的请求方式对提高开发效率非常有帮助,更轻便的请求方法更直观,也更易维护.
    Alamofire是很好的网络请求框架,但是正因为如此我们才需要对其封装使得更适合个人使用.
    这种封装方式只是个人使用时的优化,可能有更好的方法,所以发出来纯属抛砖引玉.

    有问题欢迎探讨.

    相关文章

      网友评论

        本文标题:Swift.Alamofire的封装

        本文链接:https://www.haomeiwen.com/subject/nowcgftx.html