对于Alamofire咱们在这就不做多余赘述了,感兴趣的可以去官网看一下.下面我们进入这次的主题-Moya.
Moya 的基本用法是创建请求枚举类型,然后实现TargetType协议.比较简单、霸气.当然这不是我们今天说的重点,下来的开始画重点了.
如果一个app有一百个或者更多的请求时,如何优雅的使用Moya库呢.首先,Moya本身没问题,那么我们都是什么样的使用姿势呢?
第一种:
创建一个大的API ,然后里面创建一百个API枚举类型,然后各种检查,各种协议实现.这一种属于最基本的用法!什么叫基本?就是完成了工作,至于工作完成的内涵,则就不登大雅之堂了.
第二种:
每一个模块创建一个大的API,然后里面创建了五十个枚举类型,然后各种检查,各种协议实现.这一种属于有思想的用法!最起码我们大家都去想了,也做出了自己的努力
那么问题来了?有没有更合适的方案呢!!!
划重点
那就是我们今天要说的方案了.
官网的各种用法,我就不做详细说明了,相信大家都有自己的开发经验.如果说不是那两种方案,让你设计一下,你会考虑从什么地方优化呢?我们大多都会想到如何去缩减冗余及如何优化内存和性能什么的.至于性能这块咱们就不浪费口舌了,那么如何去缩减冗余呢?
在这里我们采用三层设计方案来解决项目网络层优化问题.
第一层:数据处理层 - LTMNetworkDeal
在这里有我们的数据处理中心,上代码
dealResult(targetName: String,result: Result<Response, MoyaError>, successClosure:((_ result: Any) -> ())? = nil, failureClosure:((_ errorCode: Int, _ errorMessage: String) ->())? = nil)
数据处理入口,
switch moyaResponse.statusCode {
case 200:
guard let resultDic: [String: Any] = try? moyaResponse.mapJSON() as? [String : Any],
let code: Int = resultDic["code"] as? Int
else { return }
print("统一显示返回数据 \(resultDic)")
switch code {
case 200:
guard let systemEntity: [String: Any] = resultDic["entity"] as? [String : Any] else {
successClosure?(self.success200Deal(response: resultDic, targetName: targetName ))
return
}
successClosure?(self.success200Deal(response: systemEntity, targetName: targetName ))
case 400:
if let errorServerMes = resultDic["message"]{
failureClosure?(400, self.error400Deal(response: errorServerMes) ?? "服务器异常,未确认错误信息")
}
case 403:
if let errorServerMes = resultDic["message"]{
failureClosure?(403, self.error403Deal(response: errorServerMes) ?? "服务器异常,未确认错误信息")
}
case 500:
if let errorServerMes = resultDic["message"]{
failureClosure?(500, self.error500Deal(response: errorServerMes) ?? "服务器异常,未确认错误信息")
}
default:
print("errorServerMes")
}
case 404:
failureClosure?(moyaResponse.statusCode,"api地址错误,请内部开发人员修改后重试")
case 500:
failureClosure?(moyaResponse.statusCode,"服务器响应错误,请内部开发人员修改后重试")
case 502:
failureClosure?(moyaResponse.statusCode, self.error502Deal(response: "errorServerMes") ?? "服务器异常,未确认错误信息")
default:
failureClosure?(moyaResponse.statusCode, self.error500Deal(response: "errorServerMes") ?? "服务器异常,未确认错误信息")
break
数据详细处理阶段,
func success200Deal(response: [String : Any], targetName: String) -> Any{
return response
}
func error400Deal(response: Any) -> String?{
if let errorInfo:[String: Any] = response as? [String : Any]{
return errorInfo["message"] as? String
}else{
return "error400Deal"
}
}
func error403Deal(response: Any) -> String?{
if let errorInfo:[String: Any] = response as? [String : Any]{
return errorInfo["message"] as? String
}else{
return "error403Deal"
}
}
func error500Deal(response: Any) -> String?{
if let errorInfo:[String: Any] = response as? [String : Any]{
return errorInfo["message"] as? String
}else{
return "error500Deal"
}
}
func error502Deal(response: Any) -> String?{
if let errorInfo:[String: Any] = response as? [String : Any]{
return errorInfo["message"] as? String
}else{
return "error502Deal"
}
}
func errorRequestDeal(response: Any) -> String{
print("柯南 Deal errorRequestDeal info response success response - \(response)")
return "errorRequestDeal"
}
第二层:API层 - LTMMoyaLoginApiService、LTMMoyaHomeApiService...
这个就不详细赘述了,和Moya上基本一致.
在使用上,可以采用一些省略处理.
EG:
var task: Task {
switch self {
case .login:
return .requestParameters(parameters: param, encoding: JSONEncoding.default)
default:
return .requestParameters(parameters: param, encoding: URLEncoding.default)
}
合理使用default,你会发现你会省很多代码.
!!! 但是不建议path协议实现采用,防止接口忘记写的情况
第三层:网络处理层 - LTMMoyaNetworkManager:LTMNetworkDeal
网络层继承于第一层数据处理层LTMNetworkDeal,然后在使用的时候采用如下方案
//MARK: - 登录请求
private var loginProvider = MoyaProvider<LTMMoyaLoginApiService>(plugins: [NetworkLoggerPlugin()])
public func merchantLoginModuleRequest(target: LTMMoyaLoginApiService, targetName: String, successClosure:((_ result: Any) -> ())? = nil, failureClosure:((_ errorCode: Int, _ errorMessage: String) ->())? = nil){
loginProvider.request(target) { (result) in
self.dealResult(targetName: targetName, result: result,successClosure: successClosure, failureClosure: failureClosure)
}
}
//MARK: - 首页接口
private var homeProvider = MoyaProvider<LTMMoyaHomeApiService>(plugins: [NetworkLoggerPlugin()])
public func merchantSalesApplyModuleRequest(target: LTMMoyaHomeApiService, targetName: String, successClosure:((_ result: Any) -> ())? = nil, failureClosure:((_ errorCode: Int, _ errorMessage: String) ->())? = nil){
homeProvider.request(target) { (result) in
self.dealResult(targetName: targetName, result: result,successClosure: successClosure, failureClosure: failureClosure)
}
}
这样的话基本上把整个网络拆开了,而且更有条理性.
这块有一点需要简要说明一下,本地采用的时候传递了一个targetName,这个是做后续扩展使用的.还会持续更新.至于如何使用,大家其实心中已经有数了吧,好了,让我们下次揭晓咯.
说一千道一万,不如Demo转一转.
希望大家喜欢哈.
2020.05.18补充:
Moya续已经把我们遗留的补充了,目前已经可以完整使用了哈.