前言
這幾個(gè)月因?yàn)橛捎诟鞣N事各種忙,所以都沒有寫文章奕巍。還有一個(gè)比較重要的原因就是不知道寫哪些比較有質(zhì)量的文章來供大家閱讀化漆,這樣說來的話拗军,恰恰是違反了我自己寫文章的初心:記錄自己日常開發(fā)遇到的問題以及解決方案憾筏,目的是供自己和他人以后查閱。
閑話不多說花鹅,前段時(shí)間由于公司需要設(shè)計(jì) swift
語言編寫的公共庫氧腰。所以,我這邊除了研究整個(gè)公共庫的整體設(shè)計(jì)之外刨肃,還重點(diǎn)研究了關(guān)于 swift
網(wǎng)絡(luò)框架以及相關(guān)第三方庫的設(shè)計(jì)源碼和設(shè)計(jì)思想古拴。
框架設(shè)計(jì)
ALNetWorkingSwift
框架是我前段時(shí)間研究 AFNetworking、Alamofire真友、Moya黄痪、HandyJSON 和 ObjectMapper 等框架,總結(jié)提煉出的網(wǎng)絡(luò)框架盔然。不過相對(duì)于 Moya
這個(gè)框架來說桅打, ALNetWorkingSwift
是一個(gè)比較輕量級(jí)的網(wǎng)絡(luò)框架。
設(shè)計(jì)初心
其實(shí)愈案,編寫和設(shè)計(jì)這個(gè) ALNetWorkingSwift
框架為了解決的一個(gè)問題就是能夠讓開發(fā)者在 Swift
項(xiàng)目中挺尾,可以更加快速方便的發(fā)起 HTTP/HTTPS 請(qǐng)求,并且能夠直接拿到已經(jīng)映射好的 Model
模型站绪,自動(dòng)打印出接收到的數(shù)據(jù)遭铺。
依賴關(guān)系
為了解決開發(fā)者能夠直接能拿到網(wǎng)絡(luò)請(qǐng)求返回的數(shù)據(jù)模型,以及能夠方便的發(fā)起網(wǎng)絡(luò)請(qǐng)求恢准。這邊選用的是對(duì) Alamofire
和 HandyJSON
進(jìn)行二次封裝魂挂。其中, Alamofire
網(wǎng)絡(luò)框架是發(fā)起網(wǎng)絡(luò)請(qǐng)求馁筐,HandyJSON
則是用于映射生成 Model
涂召。
ALNetWorkingSwift
框架的依賴關(guān)系以及需要達(dá)到的效果圖如下:
架構(gòu)圖
ALNetWorkingSwift
框架,其中有一個(gè) Core
模塊眯漩,開發(fā)者可用直接使用 cocoapods
只依賴 Core
模塊芹扭,整體的架構(gòu)如下圖所示:
[圖片上傳失敗...(image-1e58f3-1542529899141)]
如上圖所示麻顶,開發(fā)者主要是調(diào)用 ALNetHTTPRequestOperationManager
類進(jìn)行網(wǎng)絡(luò)請(qǐng)求,其中可以通過 ALNetHTTPCommonConfig
進(jìn)行基本配置舱卡,最后請(qǐng)求后回調(diào)的結(jié)構(gòu)體是遵守 ALNetHTTPResponse
協(xié)議的結(jié)構(gòu)體辅肾。結(jié)構(gòu)體里面定義的 data
字段是一個(gè)泛型用于業(yè)務(wù)中使用。所以轮锥,可以根據(jù)不同的項(xiàng)目依賴 Core
模塊矫钓,在項(xiàng)目中定制適合自己的網(wǎng)絡(luò)請(qǐng)求模塊。
在架構(gòu)圖中舍杜,網(wǎng)絡(luò)請(qǐng)求是基于 Core
模塊進(jìn)行發(fā)送請(qǐng)求和解析數(shù)據(jù)的新娜。目前,這個(gè)模塊封裝的比較輕量級(jí)既绩,靈活性也比較高概龄。接下來具體介紹 Core
模塊的架構(gòu),如下圖所示:
基本使用說明
您可以調(diào)用該方法來初始化一個(gè)通用的網(wǎng)絡(luò)請(qǐng)求:
ALHTTPRequestOperationManager.default.requestBase(httpMethod: .get, url: "https://www.baidu.com", urlEncoding: TURLEncoding.default, parameter: nil) { (response) in
switch response.result {
case .success(let res):
print(res)
case .failure(let err):
print(err)
}
}
您也可以調(diào)用以下方法來上傳數(shù)據(jù):
ALHTTPRequestOperationManager.default.uploadBase(url: "https://www.baidu.com", multipartFormData: { (formData) in
// The assembly to upload data
}) { (result) in
switch result {
case .success(let request, let streamingFromDisk, let streamFileURL):
print(request)
print(streamingFromDisk)
print(streamFileURL ?? "")
case .failure(let err):
print(err)
}
}
此處返回的成功或失敗的判定是相對(duì)于服務(wù)器而言的饲握,而不是業(yè)務(wù)相關(guān)的狀態(tài)碼私杜。也就是說網(wǎng)絡(luò)請(qǐng)求收到的不合法的數(shù)據(jù)或者服務(wù)器異常的情況,會(huì)判定失敗救欧。
高級(jí)用法
您還可以重新封裝這兩種方法以滿足業(yè)務(wù)需求衰粹。
為了符合 ALCommonConfigProtocol
,結(jié)構(gòu)體需要實(shí)現(xiàn)一些屬性和方法:
public struct HTTPConfig: ALCommonConfigProtocol {
public var kHttpUserAgent: String = ""
init() {
}
public func getHeader(dictHeader: [String: String]? = nil) -> [String: String] {
var header: [String:String] = [String: String]()
if dictHeader != nil {
header.merge(dictHeader!) { (_, new) in new }
}
return header
}
public func getContentType(contentType: Set<String>? = nil) -> Set<String> {
var content: Set<String> = Set<String>()
contentType?.forEach({ (ele) in
content.insert(ele)
})
return content
}
}
然后,調(diào)用這個(gè)方法:
ALHTTPRequestOperationManager.default.httpConfig = HTTPConfig()