封裝 一個(gè)面向協(xié)議的網(wǎng)絡(luò)請(qǐng)求
Bamboots 是基于 Alamofire
的一系列擴(kuò)展庫(kù)璧诵,這個(gè)庫(kù) 充分的體現(xiàn)了 面向 Protocol
編程在組合設(shè)計(jì)模式中的應(yīng)用腻格。
目前我對(duì) network request
的希望是: 傳入一個(gè)請(qǐng)求體:form
妒蔚,然后給我返回: 成功后的模型對(duì)象承疲、失敗后的 error
對(duì)象
let form = WeatherForm<RootModel>()
request(
form,
success: { (response) in
print(response.data.three_day_forecast.count)
}) { (error) in
print(error.localizedDescription)
}
當(dāng)我們也可以根據(jù)需要來(lái)處理結(jié)果焰络,有時(shí)候我們對(duì)請(qǐng)求成功后的結(jié)果感興趣鸥滨,有時(shí)候我們需要對(duì)請(qǐng)求失敗后的 error
做特殊處理:
func request<T: Codable>(
_ form: WeatherForm<T>,
success: ((T) -> Void)? = nil ,
failure: ((_ error: Error) -> Void)? = nil
)
如上的接口就能滿足我們的需要嗦哆,我們的 form
提供了所有的請(qǐng)求信息, success
婿滓、 failure
兩個(gè)閉包就是我們可以根據(jù)當(dāng)前網(wǎng)絡(luò)請(qǐng)求的需要來(lái)進(jìn)行處理了老速。當(dāng)然我們對(duì)應(yīng)的閉包傳入 nil
或做缺省處理,這樣就會(huì)使用我們的默認(rèn)實(shí)現(xiàn)了凸主。然后在默認(rèn)實(shí)現(xiàn)里統(tǒng)一處理相關(guān)信息橘券,當(dāng)然這也是工程的一部分了,需要根據(jù)具體項(xiàng)目而定了卿吐。讓我們看一下 WeatherForm<RootModel>()
這個(gè)表單里面攜帶了我們網(wǎng)絡(luò)請(qǐng)求的一些條件信息旁舰,包括: api
、method
嗡官、hearders
箭窜、parameters
, 還有我們需要返回的模型類(lèi)型RootModel
。這些信息中有些是高頻修改的衍腥,如 api
磺樱、method
、parameters
紧阔,對(duì)于 api
坊罢、method
我們通過(guò) enum
統(tǒng)一管理,對(duì)于 parameters
我們則通過(guò)屬性做map
來(lái)簡(jiǎn)化請(qǐng)求參數(shù)的賦值擅耽, 而對(duì)于 hearders
這種修改頻率低的我們可以做統(tǒng)一處理,在需要修改時(shí)再添加extension
實(shí)現(xiàn), 如:
extension Formable {
public func headers() -> [String: String] {
return ["accessToken": "xxx"]
}
}
extension Formable where Self: RequestFormable {
public func headers() -> [String: String] {
return [
"accessToken": "xxx", "fileName": "xxx",
"App-Source": "APP",
"User-Os": "iOS",
]
}
}
extension Formable where Self: UploadFormable {
public func headers() -> [String: String] {
return ["accessToken": "xxx", "fileName": "xxx"]
}
}
這里的 WeatherForm<RootModel>()
繼承了 GetForm
當(dāng)然以上這些是基于 Bamboots
而封裝的物遇。我們的 Bamboots
在 Swift 3
時(shí)是基于 AlamofireObjectMapper
的乖仇,當(dāng)然這在 Swift 4
中, 我們?nèi)《褂玫木褪?AlamofireCodable, 從命名上就可以看出來(lái)询兴,功能是一樣的乃沙,只是在 Swift 4
中我們有了 Codable
我們就可以祛除ObjectMapper
了,也許不久我們直接就可以在 Alamofire 看到相應(yīng)的實(shí)現(xiàn)了诗舰,
此圖為證警儒。
AlamofireCodable
在 Alamofire
的基礎(chǔ)上為DataRequest
添加了兩個(gè)擴(kuò)展函數(shù):
/// Adds a handler to be called once the request has finished.
///
/// - Parameters:
/// - queue: The queue on which the completion handler is dispatched.
/// - keyPath: The key path where object mapping should be performed
/// - completionHandler: A closure to be executed once the request has finished and the data has been decoded by JSONDecoder.
/// - Returns: The request.
@discardableResult
public func responseObject<T: Codable>(queue: DispatchQueue? = nil, keyPath: String? = nil, completionHandler: @escaping (DataResponse<T>) -> Void) -> Self {
return response(queue: queue, responseSerializer: DataRequest.ObjectSerializer(keyPath), completionHandler: completionHandler)
}
通過(guò)調(diào)用 responseObject
直接在回調(diào)中返回含有T
對(duì)象的DataResponse<T>
,而下面這個(gè)函數(shù)
/// Adds a handler to be called once the request has finished. T: Codable
///
/// - Parameters:
/// - queue: The queue on which the completion handler is dispatched.
/// - keyPath: The key path where object mapping should be performed
/// - completionHandler: A closure to be executed once the request has finished and the data has been decoded by JSONDecoder.
/// - Returns: The request.
@discardableResult
public func responseArray<T: Codable>(queue: DispatchQueue? = nil, keyPath: String? = nil, completionHandler: @escaping (DataResponse<[T]>) -> Void) -> Self {
return response(queue: queue, responseSerializer: DataRequest.ObjectArraySerializer(keyPath), completionHandler: completionHandler)
}
則提供了對(duì)數(shù)組的支持。