前言
我们网络请求后得到数据需要转模型,一般项目就是使用一种解析数据的方式,常见的Codable、Swiftyjson、Handyjson
等,一般的做法就是在定义方法时就传一个泛型,例如(T: Codable)这样然后解析。但是如果既有Codable又有Swiftyjson这样就不好同时让泛型T
遵循2个协议。所以这里就可以用到关联类型来将处理。
1、抽离一个转模型的协议
protocol NetResponseParseAble {
associatedtype NetResult
func parse(_ response: Data) throws -> NetResult
}
NetResult
关联类型就是需要解析的类型,遵循NetResponseParseAble
来解析模型。
2、封装一个NetTool做网络请求
这里我们返回出去的就是NetResponseParseAble
的关联类型NetResult,也就是我们处理好的模型
struct NetTool {
// 一个request请求,这里是以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做网络请求获取到返回值Data
// 做一些项目相关判断操作
// 解析
do {
let result = P.parse(response.data)
completion(result)
} catch {
处理错误
}
}
}
3、实现NetResponseParseAble
不同的转模型方式
// 一般接口返回长这样
struct NetResponse<T: Decodable>: Decodable {
let code: Int
let message: String?
let data: T?
}
1、Codable转模型
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 错误
}
return data
}catch {
throw error
}
}
}
2、swiftyjson转模型
protocol SwiftyJsonType {
init(json: JSON)
}
struct NetSwiftyJsonResponseParser<T: SwiftyJsonType>: NetResponseParseAble {
func parse(_ data: Data) throws -> T {
// 这里没写完整,大概这样
let res = T(json: data)
return res
}
}
4、在NetTool中创建对应解析方法
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 {
// 这里做网络请求获取到返回值Data
// 做一些判断操作
// 解析
do {
let result = P.parse(response.data)
completion(result)
} catch {
处理错误
}
}
}
这样以后增加一种解析方式只需要再创建一个结构体或类遵循NetResponseParseAble
协议实现协议方法就可以了。