Swift.Alamofire的封裝

實(shí)現(xiàn)功能:

自動(dòng)緩存,網(wǎng)絡(luò)狀態(tài)監(jiān)聽,無網(wǎng)絡(luò)狀態(tài)自動(dòng)調(diào)用緩存數(shù)據(jù).

統(tǒng)一全局manager,一次設(shè)定baseURL與header.全局使用.

優(yōu)化調(diào)用方式,使網(wǎng)絡(luò)請(qǐng)求更輕便,更直觀.

使用第三方庫(kù):

Alamofire: 核心功能,網(wǎng)絡(luò)請(qǐng)求.

SwiftyJSON: 數(shù)據(jù)緩存時(shí)使用,方便地處理JSON數(shù)據(jù).

/建議配合使用MBProgressHud,但因?yàn)榉潜仨?demo中去掉了./


1.自動(dòng)緩存

在網(wǎng)絡(luò)請(qǐng)求成功時(shí)調(diào)用,將數(shù)據(jù)存儲(chǔ).

/// 進(jìn)行數(shù)據(jù)緩存
    ///
    /// - Parameters:
    ///   - responseObject: 緩存數(shù)據(jù)
    ///   - request: 請(qǐng)求
    ///   - parameters: 參數(shù)
    public func cacheResponseObject(responseObject: AnyObject,
                                    request: URLRequest,
                                    parameters: [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請(qǐng)求下的參數(shù)拼接到url上
            let absoluterURL = self.generateGETAbsoluteURL(url: (request.url?.absoluteString)!, parameters)
            ///對(duì)url進(jìn)行md5加密
            let key = absoluterURL.md5()
            ///將加密過的url作為目錄拼接到默認(rèn)路徑
            let path = directoryPath.appending(key)
            ///將請(qǐng)求數(shù)據(jù)轉(zhuǎn)換成data
            let dict: AnyObject = responseObject
            var data: Data?
            do {
                try data = JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
            } catch {
            }
            ///將data存儲(chǔ)到指定路徑
            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.網(wǎng)絡(luò)狀態(tài)監(jiān)聽.

///監(jiān)聽網(wǎng)絡(luò)狀態(tài)
    public func detectNetwork(netWorkStatus: @escaping ELNetworkStatus) {
        let reachability = NetworkReachabilityManager()
        reachability?.startListening()
        reachability?.listener = { [weak self] status in
            guard let weakSelf = self else { return }
            if reachability?.isReachable ?? false {
                switch status {
                case .notReachable:
                    weakSelf.ewNetworkStatus = EWNetworkStatus.notReachable
                case .unknown:
                    weakSelf.ewNetworkStatus = EWNetworkStatus.unknown
                case .reachable(.wwan):
                    weakSelf.ewNetworkStatus = EWNetworkStatus.wwan
                case .reachable(.ethernetOrWiFi):
                    weakSelf.ewNetworkStatus = EWNetworkStatus.wifi
                }
            } else {
                weakSelf.ewNetworkStatus = EWNetworkStatus.notReachable
            }
            netWorkStatus(weakSelf.ewNetworkStatus.rawValue)
        }
    }

3.無網(wǎng)絡(luò)時(shí)獲取緩存數(shù)據(jù)

     ///從緩存中獲取數(shù)據(jù)
    public func cahceResponseWithURL(url: String, paramters: [String: Any]?) -> Any? {
        var cacheData: Any?
        let directorPath = cachePath
        let absoluteURL = self.generateGETAbsoluteURL(url: url, paramters)
        ///使用md5進(jìn)行加密
        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
    }
   ///解析緩存數(shù)據(jù)
    public func successResponse(responseData: Any, callback success: EWResponseSuccess) {
        success(self.tryToParseData(responseData: responseData))
    }
    ///解析數(shù)據(jù)
    public func tryToParseData(responseData: Any) -> AnyObject {
        guard let data = responseData as? Data else {
            return responseData as AnyObject
        }
        do {
            let json =  try JSON(data: data)
            return json as AnyObject
        } catch {
            return responseData as AnyObject
        }
    }

4.設(shè)定manager

    private lazy var manager: SessionManager = {
        let config: URLSessionConfiguration = URLSessionConfiguration.default
        let serverTrustPolicies: [String: ServerTrustPolicy] = [
            ///正式環(huán)境的證書配置,修改成自己項(xiàng)目的正式url
            "www.baidu.com": .pinCertificates(
                certificates: ServerTrustPolicy.certificates(),
                validateCertificateChain: true,
                validateHost: true
            ),
            ///測(cè)試環(huán)境的證書配置,不驗(yàn)證證書,無腦通過
            "192.168.1.213:8002": .disableEvaluation
            ]
        config.httpAdditionalHeaders = ewHttpHeaders
        config.timeoutIntervalForRequest = ewTimeout
        //根據(jù)config創(chuàng)建manager
        return SessionManager(configuration: config,
                                 delegate: SessionDelegate(),
                                 serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
    }()

5.核心網(wǎng)絡(luò)請(qǐng)求功能

    ///核心方法
    public func requestWith(url: String,
                            httpMethod: Int32,
                            params: [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進(jìn)行調(diào)試.
        if let params = params {
            print("\(lastUrl)\nheader =\(String(describing: ewHttpHeaders))\nparams = \(params)")
        } else {
            print("\(lastUrl)\nheader =\(String(describing: ewHttpHeaders))")
        }
        //get
        if httpMethod == 0 {
            //無網(wǎng)絡(luò)狀態(tài)獲取緩存
            if ewNetworkStatus.rawValue == EWNetworkStatus.notReachable.rawValue
                || ewNetworkStatus.rawValue == EWNetworkStatus.unknown.rawValue {
                let response = self.cahceResponseWithURL(url: lastUrl,
                                                                 paramters: params)
                if response != nil {
                    self.successResponse(responseData: response!, callback: success)
                } else {
                    return
                }
            }
            manageGet(url: lastUrl, params: params, success: success, error: error)
        } else {
            managePost(url: lastUrl, params: params!, success: success, error: error)
        }
    }
    private func managePost(url: String,
                            params: [String: Any],
                            success: @escaping EWResponseSuccess,
                            error: @escaping EWResponseFail) {
        manager.request(url,
                        method: .post,
                        parameters: params,
                        encoding: JSONEncoding.default,
                        headers: nil).responseJSON { (response) in
                            switch response.result {
                            case .success:
                                ///添加一些全部接口都有的一些狀態(tài)判斷
                                if let value = response.result.value as? [String: Any] {
                                    if value["status"] as? Int == 1010 {
                                        error("登錄超時(shí),請(qǐng)重新登錄" as AnyObject)
                                        _ = Keychain.clear()
                                        return
                                    }
                                    success(value as AnyObject)
                                }
                            case .failure(let err):
                                error(err as AnyObject)
                                debugPrint(error)
                            }
        }
    }
    private func manageGet(url: String,
                           params: [String: Any]?,
                           success: @escaping EWResponseSuccess,
                           error: @escaping EWResponseFail) {
        manager.request(url,
                        method: .get,
                        parameters: params,
                        encoding: URLEncoding.default,
                        headers: nil).responseJSON { (response) in
                            switch response.result {
                            case .success:
                                if let value = response.result.value as? [String: Any] {
                                    ///添加一些全部接口都有的一些狀態(tài)判斷
                                    if value["status"] as? Int == 1010 {
                                        error("登錄超時(shí),請(qǐng)重新登錄" as AnyObject)
                                        _ = Keychain.clear()
                                        return
                                    }
                                    success(value as AnyObject)
                                    //緩存數(shù)據(jù)
                                    self.cacheResponseObject(responseObject: value as AnyObject,
                                                             request: response.request!,
                                                             parameters: nil)
                                }
                            case .failure(let err):
                                error(err as AnyObject)
                                debugPrint(err)
                            }
        }
    }

6.添加請(qǐng)求方法

extension EWNetworking {
    ///get請(qǐng)求demo
    public func getDataTest(test: String,
                            success: @escaping EWResponseSuccess,
                            failure: @escaping EWResponseFail) {
        let path = "test"
        EWNetworking.ShareInstance.getWith(url: path, params: ["id": test], success: { (response) in
            guard let json = response as? [String: Any] else { return }
            ///保證接口調(diào)通, 否則返回錯(cuò)誤信息
            guard json["status"] as? NSNumber == 1 else {
//                MBProgressHud.showTextHudTips(message: json["msg"] as? String)
                print(json["msg"] as? String ?? "")
                failure(response)
                return
            }
            guard let dict = json["obj"] as? [String: Any] else {
                failure(NSError(domain: "轉(zhuǎn)字典失敗", code: 2000, userInfo: nil))
                return
            }
            guard let dataArray = dict["data"] else {
                failure(NSError(domain: "獲取數(shù)組失敗", code: 2000, userInfo: nil))
                return
            }
            success(dataArray as AnyObject)
        },error: { (error) in
            failure(error)
//            MBProgressHud.showTextHudTips(message: "網(wǎng)絡(luò)請(qǐng)求錯(cuò)誤")
        })
    }
    ///post請(qǐng)求demo
    public func postDataTest(test: String,
                             success: @escaping EWResponseSuccess,
                             failure: @escaping EWResponseFail) {
        let path = "v1/passport/register"
        EWNetworking.ShareInstance.postWith(url: path, params: ["id": test], 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"] as? String ?? "")
                failure(response)
                return
            }
            success(response as AnyObject)
        },error: { (error) in
            failure(error)
            //            MBProgressHud.showTextHudTips(message: "網(wǎng)絡(luò)請(qǐng)求錯(cuò)誤")
        })
    }
}

7.調(diào)用請(qǐng)求demo

     func getDemo() {
        EWNetworking.ShareInstance.getDataTest(test: "1", success: { [weak self] (response) in
            guard let weakSelf = self else { return }
            guard let model = response as? [String] else { return }
            ///根據(jù)獲取model來進(jìn)行相應(yīng)操作
        }, failure: { (_) in
        })

    }
    func postDemo() {
        EWNetworking.ShareInstance.postDataTest(test: "1", success: { [weak self] (response) in
            guard let weakSelf = self else { return }
            guard let model = response as? [String] else { return }
            ///根據(jù)獲取model來進(jìn)行相應(yīng)操作
        }, failure: { (_) in
        })
    }

demo地址:AlamofireEncapsulation

網(wǎng)絡(luò)請(qǐng)求是開發(fā)中非常非常核心的一部分,也是非常非常常用的一部分,所以優(yōu)化我們的請(qǐng)求方式對(duì)提高開發(fā)效率非常有幫助,更輕便的請(qǐng)求方法更直觀,也更易維護(hù).
Alamofire是很好的網(wǎng)絡(luò)請(qǐng)求框架,但是正因?yàn)槿绱宋覀儾判枰獙?duì)其封裝使得更適合個(gè)人使用.
這種封裝方式只是個(gè)人使用時(shí)的優(yōu)化,可能有更好的方法,所以發(fā)出來純屬拋磚引玉.

有問題歡迎探討.


于2018.10.23進(jìn)行實(shí)例化更新
于2019.02.18根據(jù)swiftlint進(jìn)行代碼規(guī)范更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毫捣,一起剝皮案震驚了整個(gè)濱河市线召,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌双饥,老刑警劉巖蚯姆,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件五续,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡龄恋,警方通過查閱死者的電腦和手機(jī)疙驾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郭毕,“玉大人它碎,你說我怎么就攤上這事∠匝海” “怎么了扳肛?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)乘碑。 經(jīng)常有香客問我挖息,道長(zhǎng),這世上最難降的妖魔是什么兽肤? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任套腹,我火速辦了婚禮,結(jié)果婚禮上资铡,老公的妹妹穿的比我還像新娘电禀。我一直安慰自己,他們只是感情好笤休,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布尖飞。 她就那樣靜靜地躺著,像睡著了一般店雅。 火紅的嫁衣襯著肌膚如雪政基。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天底洗,我揣著相機(jī)與錄音腋么,去河邊找鬼。 笑死亥揖,一個(gè)胖子當(dāng)著我的面吹牛珊擂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播费变,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼摧扇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了挚歧?” 一聲冷哼從身側(cè)響起扛稽,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滑负,沒想到半個(gè)月后在张,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體用含,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年帮匾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了啄骇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瘟斜,死狀恐怖缸夹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情螺句,我是刑警寧澤虽惭,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站蛇尚,受9級(jí)特大地震影響芽唇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜佣蓉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一披摄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勇凭,春花似錦疚膊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至璧函,卻和暖如春傀蚌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蘸吓。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工善炫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人库继。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓箩艺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親宪萄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艺谆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽明先生_X自主閱讀 15,981評(píng)論 3 119
  • 某些拜英,曾經(jīng)你最不希望它發(fā)生的事情静汤,在有一天,你突然發(fā)現(xiàn)它竟然已經(jīng)發(fā)生了,可能你也不知道它從什么時(shí)候開始變成那樣的虫给,...
    大海獅閱讀 525評(píng)論 0 0
  • 02021500#卓有成效的管理者#閱讀體會(huì):1藤抡、有效的管理就是把事情做對(duì)而不是做對(duì)的事;而管理者本身的思考就是工...
    知行大學(xué)閱讀 487評(píng)論 0 0