前言
我們網(wǎng)絡(luò)請(qǐng)求后得到數(shù)據(jù)需要轉(zhuǎn)模型,一般項(xiàng)目就是使用一種解析數(shù)據(jù)的方式,常見的Codable、Swiftyjson、Handyjson等,一般的做法就是在定義方法時(shí)就傳一個(gè)泛型,例如(T: Codable)這樣然后解析。但是如果既有Codable又有Swiftyjson這樣就不好同時(shí)讓泛型T遵循2個(gè)協(xié)議。所以這里就可以用到關(guān)聯(lián)類型來(lái)將處理。
1、抽離一個(gè)轉(zhuǎn)模型的協(xié)議
protocol NetResponseParseAble {
associatedtype NetResult
func parse(_ response: Data) throws -> NetResult
}
NetResult關(guān)聯(lián)類型就是需要解析的類型,遵循NetResponseParseAble來(lái)解析模型。
2、封裝一個(gè)NetTool做網(wǎng)絡(luò)請(qǐng)求
這里我們返回出去的就是NetResponseParseAble的關(guān)聯(lián)類型NetResult,也就是我們處理好的模型
struct NetTool {
// 一個(gè)request請(qǐng)求,這里是以moya為例
@discardableResult
static func request<R: TargetType, P: NetResponseParseAble>(_ request: R,
parser: P,
progressClosure: NetProgressClosure? = nil,
completion: OneResult<P.NetResult?>?,
errorClosure: NetErrorClosure? = nil) -> Cancellable {
// 這里用moya做網(wǎng)絡(luò)請(qǐng)求獲取到返回值Data
// 做一些項(xiàng)目相關(guān)判斷操作
// 解析
do {
let result = P.parse(response.data)
completion(result)
} catch {
處理錯(cuò)誤
}
}
}
3、實(shí)現(xiàn)NetResponseParseAble不同的轉(zhuǎn)模型方式
// 一般接口返回長(zhǎng)這樣
struct NetResponse<T: Decodable>: Decodable {
let code: Int
let message: String?
let data: T?
}
1、Codable轉(zhuǎn)模型
struct NetDecodableResponseParser<T: Decodable>: NetResponseParseAble {
func parse(_ data: Data) throws -> T {
do {
let r = try response.map(NetResponse<T>.self)
guard let data = r.data else {
throw 錯(cuò)誤
}
return data
}catch {
throw error
}
}
}
2、swiftyjson轉(zhuǎn)模型
protocol SwiftyJsonType {
init(json: JSON)
}
struct NetSwiftyJsonResponseParser<T: SwiftyJsonType>: NetResponseParseAble {
func parse(_ data: Data) throws -> T {
// 這里沒(méi)寫完整,大概這樣
let res = T(json: data)
return res
}
}
4、在NetTool中創(chuàng)建對(duì)應(yīng)解析方法
struct NetTool {
@discardableResult
static func fetch<T: SwiftyJsonType>(_ request: TargetType,
resultType: T.Type,
progressClosure: NetProgressClosure? = nil,
completion: OneResult<T?>?,
errorClosure: NetErrorClosure? = nil) -> Cancellable {
return NetTool.request(
request,
parser: NetSwiftyJsonResponseParser<T>(),
progressClosure: progressClosure,
completion: completion,
errorClosure: errorClosure)
}
@discardableResult
static func fetch<T: Codable>(_ request: TargetType,
resultType: T.Type,
progressClosure: NetProgressClosure? = nil,
completion: OneResult<T?>?,
errorClosure: NetErrorClosure? = nil) -> Cancellable {
return NetTool.request(
request,
parser: NetDecodableResponseParser<T>(),
progressClosure: progressClosure,
completion: completion,
errorClosure: errorClosure)
}
@discardableResult
static func request<R: TargetType, P: NetResponseParseAble>(_ request: R,
parser: P,
progressClosure: NetProgressClosure? = nil,
completion: OneResult<P.NetResult?>?,
errorClosure: NetErrorClosure? = nil) -> Cancellable {
// 這里做網(wǎng)絡(luò)請(qǐng)求獲取到返回值Data
// 做一些判斷操作
// 解析
do {
let result = P.parse(response.data)
completion(result)
} catch {
處理錯(cuò)誤
}
}
}
這樣以后增加一種解析方式只需要再創(chuàng)建一個(gè)結(jié)構(gòu)體或類遵循NetResponseParseAble協(xié)議實(shí)現(xiàn)協(xié)議方法就可以了。