项目开发中的接口比较多,在使用moya时会使用多个类,为避免一些代买的重复书写,做了一些封装处理,网络使用Alamofire,数据解析使用Moya-ObjectMapper
-
首先是对返回数据统一处理的模型
import ObjectMapper import Moya
class ResponseModel: NSObject,Mappable {
1/// 返回码 2var code:Int = 0 3/// 信息 4var message:String = "" 5/// 数据 6var data:Any? 7 8override init() {super.init()} 9 10init(_ code: Int, message:String, data:Any? = nil) { 11 self.code = code 12 self.message = message 13 self.data = data 14} 15 16class func success(_ data:Any) ->ResponseModel{ 17 return ResponseModel(200, message: "SUCCESS", data: data) 18} 19 20class func faild(_ message:String? = "FAILD") ->ResponseModel{ 21 return ResponseModel(400, message: message ?? "FAILD", data: nil) 22} 23 24required init?(map: Map) {} 25 26func mapping(map: Map) { 27 code <- map["code"] 28 message <- map["message"] 29 data <- map["data"] 30}}
-
然后是对返回数据的统一 处理工具
import Moya
class NetWorkManager {
1/// 处理成功的返回结果 2static func getResponse(_ success:Moya.Response) ->ResponseModel { 3 var responseModel:ResponseModel = ResponseModel() 4 do { 5 responseModel = try success.mapObject(ResponseModel.self) 6 }catch{ 7 responseModel.code = 200 8 responseModel.message = "无法解析网络返回数据" 9 } 10 //TODO: 根据各自业务需求,可对一些返回结果做出特殊处理😅 11 if responseModel.code == 200 ,responseModel.message == "SUCCESS",responseModel.data == nil { 12 responseModel.message = "没有更多了" 13 } 14 return responseModel 15} 16 17/// 处理失败的返回结果 18static func getResponse(_ error:MoyaError) ->ResponseModel { 19 let responseModel:ResponseModel = ResponseModel() 20 responseModel.code = 500 21 responseModel.message = error.errorDescription ?? "网络访问出错" 22 return responseModel 23} 24 25/// 获取请求头 26/// 27/// - Parameter token: 是否包含token 28/// - Returns: <#return value description#> 29static func getHeaders(_ token:Bool? = true) ->[String:String] { 30 var result:[String:String] = ["Content-type" : "application/json"] 31 if token! { 32 result["Token"] = "这里写用户的token" 33 } 34 return result 35}}
-
再对MoyaProvider进行扩展
1import Moya 2import Alamofire 3 4extension MoyaProvider { 5 6 static func custom( 7 endpointClosure: @escaping Moya.MoyaProvider<Target>.EndpointClosure = HZJMoyaTool<Target>.endpointClosure, 8 requestClosure: @escaping Moya.MoyaProvider<Target>.RequestClosure = HZJMoyaTool<Target>.requestResultClosure, 9 stubClosure: @escaping Moya.MoyaProvider<Target>.StubClosure = HZJMoyaTool<Target>.stubClosure, 10 callbackQueue: DispatchQueue? = nil, 11 session: Moya.Session = HZJMoyaTool<Target>.session(), 12 plugins: [Moya.PluginType] = HZJMoyaTool<Target>.authPlugins(), 13 trackInflights: Bool = false) -> MoyaProvider{ 14 return MoyaProvider.init(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, callbackQueue: callbackQueue, session: session, plugins: plugins, trackInflights: trackInflights) 15 } 16 17 func hzj_Request(_ target: Target, callbackQueue: DispatchQueue? = .none, progress: ProgressBlock? = .none, finishBlock:@escaping ((ResponseModel)->Void)) { 18 self.request(target, callbackQueue: callbackQueue, progress: progress) { (result) in 19 switch result { 20 case let .success(response): 21 finishBlock(NetWorkManager.getResponse(response)) 22 case let .failure(error): 23 finishBlock(NetWorkManager.getResponse(error)) 24 } 25 } 26 } 27} -
其中的HZJMoyaTool类,其中的具体内容,大家应根据自己的项目而定
1struct HZJMoyaTool<Target: TargetType> { 2 3 static func endpointClosure(for target: Target) -> Endpoint { 4 let url = target.baseURL.appendingPathComponent(target.path).absoluteString 5 let endpoint = Endpoint(url: url, sampleResponseClosure: {.networkResponse(200,target.sampleData)}, method: target.method, task: target.task, httpHeaderFields: target.headers) 6// endpoint.adding(newHTTPHeaderFields:["Content-Type" : "application/x-www-form-urlencoded","ECP-COOKIE" : ""]) 7 return endpoint 8 } 9 10 static func requestResultClosure(for endpoint: Endpoint, closure: MoyaProvider<Target>.RequestResultClosure) { 11 do { 12 var urlRequest = try endpoint.urlRequest() 13 urlRequest.timeoutInterval = 60//设置网络超时时间 14// urlRequest.cachePolicy = .returnCacheDataElseLoad 15 closure(.success(urlRequest)) 16 } catch MoyaError.requestMapping(let url) { 17 closure(.failure(MoyaError.requestMapping(url))) 18 } catch MoyaError.parameterEncoding(let error) { 19 closure(.failure(MoyaError.parameterEncoding(error))) 20 } catch { 21 closure(.failure(MoyaError.underlying(error, nil))) 22 } 23 } 24 25 static func stubClosure(_: Target) -> Moya.StubBehavior { 26// return Moya.StubBehavior.immediate//使用sampleData中返回的测试数据 27 return Moya.StubBehavior.never 28 } 29 30 static func session() -> Session { 31 let defaultSession = MoyaProvider<Target>.defaultAlamofireSession() 32// let configuration = URLSessionConfiguration.default 33// configuration.headers = defaultSession.sessionConfiguration.headers 34// configuration.httpAdditionalHeaders = defaultSession.sessionConfiguration.httpAdditionalHeaders 35 let configuration = defaultSession.sessionConfiguration 36 if let path: String = Bundle.main.path(forResource: "xxx", ofType: "cer") { 37 ///添加证书 38 do { 39 let certificationData = try Data(contentsOf: URL(fileURLWithPath: path)) as CFData 40 if let certificate = SecCertificateCreateWithData(nil, certificationData){ 41 let certificates: [SecCertificate] = [certificate] 42 let policies: [String: ServerTrustEvaluating] = ["domain": PinnedCertificatesTrustEvaluator(certificates: certificates, acceptSelfSignedCertificates: true, performDefaultValidation: true, validateHost: true)] 43 let manager = ServerTrustManager(allHostsMustBeEvaluated: false, evaluators: policies) 44 return Session(configuration: configuration, serverTrustManager: manager) 45 } 46 } catch { 47 return Session(configuration: configuration) 48 } 49 } 50 return Session(configuration: configuration) 51 } 52 53 static func authPlugins() -> [Moya.PluginType] { 54 return [] 55// return [AccessTokenPlugin{_ in User.shared.token}] 56 } 57} -
最后再举个使用例子吧
1import Moya 2 3let LoginLogManager = MoyaProvider<LoginLogAPI>.custom() 4 5enum LoginLogAPI { 6 ///添加登录日志(type:0-web 1-app) 7 case addLoginLog(type:Int) 8} 9 10extension LoginLogAPI:TargetType { 11 var baseURL: URL { 12 return URL(string: AppRootApi + "/api/appHtLoginLog/")! 13 } 14 15 var path: String { 16 switch self { 17 case .addLoginLog(type: _): 18 return "addLoginLog" 19 } 20 } 21 22 var method: Moya.Method { 23 switch self { 24 default: 25 return .post 26 } 27 } 28 29 var sampleData: Data { 30 return "{}".data(using: String.Encoding.utf8)! 31 } 32 33 var task: Task { 34 var params:[String:Any] = [:] 35 switch self { 36 case .addLoginLog(type: let type): 37 params["type"] = type 38 return .requestCompositeParameters(bodyParameters: [:], bodyEncoding: URLEncoding.httpBody, urlParameters: params) 39 } 40 } 41 42 var headers: [String : String]? { 43 switch self { 44 default: 45 return NetWorkManager.getHeaders(true) 46 } 47 } 48}使用接口就这样
1 func test() { 2 LoginLogManager.hzj_Request(.addLoginLog(type: 1)) { [weak self](responseModel) in 3 guard let strongSelf = self else { return } 4 if responseModel.code == 200 { 5 print("成功") 6 }else{ 7 print("失败") 8 } 9 } 10 }
大概就这样,以上都是一些统一的处理,若要有一些特殊的接口,大家就只用自己弄了