iOS-study
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

NetworkManager.swift 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // NetworkManager.swift
  3. // iOSFirst
  4. //
  5. // Created by 孙宇峰 on 2023/2/22.
  6. //
  7. import Foundation
  8. import Moya
  9. import Alamofire
  10. import HandyJSON
  11. import RxSwift
  12. import SwiftyJSON
  13. /// 超时时长
  14. private var requestTimeOut:Double = 30
  15. ///endpointClosure
  16. public let myEndpointClosure = { (target: TargetType) -> Endpoint in
  17. ///这里的endpointClosure和网上其他实现有些不太一样。
  18. ///主要是为了解决URL带有?无法请求正确的链接地址的bug
  19. let url = target.baseURL.absoluteString + target.path
  20. var endpoint = Endpoint(
  21. url: url,
  22. sampleResponseClosure: { .networkResponse(200, target.sampleData) },
  23. method: target.method,
  24. task: target.task,
  25. httpHeaderFields: target.headers
  26. )
  27. switch target {
  28. default:
  29. requestTimeOut = 30//设置默认的超时时长
  30. return endpoint
  31. }
  32. }
  33. public let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
  34. do {
  35. var request = try endpoint.urlRequest()
  36. //设置请求时长
  37. request.timeoutInterval = requestTimeOut
  38. // 打印请求参数
  39. if let requestData = request.httpBody {
  40. log.info("\(request.url!)"+"\n"+"\(request.httpMethod ?? "")"+"发送参数"+"\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
  41. }else{
  42. log.info("\(request.url!)"+"\(String(describing: request.httpMethod))")
  43. }
  44. if let header = request.allHTTPHeaderFields {
  45. log.info("请求头内容\(header)")
  46. }
  47. done(.success(request))
  48. } catch {
  49. done(.failure(MoyaError.underlying(error, nil)))
  50. }
  51. }
  52. /// NetworkActivityPlugin插件用来监听网络请求
  53. public let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
  54. log.info("networkPlugin \(changeType)")
  55. //targetType 是当前请求的基本信息
  56. switch(changeType){
  57. case .began:
  58. log.info("开始请求网络")
  59. case .ended:
  60. log.info("结束")
  61. }
  62. }
  63. // https://github.com/Moya/Moya/blob/master/docs/Providers.md 参数使用说明
  64. //stubClosure 用来延时发送网络请求
  65. final class TdwMoyaPlugin: PluginType {
  66. public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
  67. var request = request
  68. request.addValue("token值", forHTTPHeaderField: "token名字")
  69. return request
  70. }
  71. }
  72. /*
  73. Moya默认有4个插件分别为:
  74. AccessTokenPlugin 管理AccessToken的插件
  75. CredentialsPlugin 管理认证的插件
  76. NetworkActivityPlugin 管理网络状态的插件
  77. NetworkLoggerPlugin 管理网络log的插件
  78. */
  79. // 插件,实现pluginType可以实现在网络请求前转菊花,请求完成结束转菊花,或者写日志等功能
  80. struct NetworkPlugin: PluginType {
  81. let userDefault=UserDefaults.standard
  82. /// Called to modify a request before sending.(可进行数据加密等)
  83. func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
  84. var mRequest = request
  85. let key = "XINGHUOLIAOYUAN7"
  86. // let jsonString = AESEncryptor.aes_encrypt(request.httpBody!.toHexString(),aes_key: key)
  87. //TODO AES加密相关
  88. let jsonString = aesEncryptData(request.httpBody,key.data(using: .utf8))
  89. // let jsonString = AESEncryptor.aes_encrypt(request.httpBody!.toHexString(),aes_key: key)
  90. //TODO AES加密相关
  91. // let jsonString = aesEncryptString(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "",key)
  92. mRequest.httpBody = jsonString?.toHexString().data(using: .utf8)
  93. print("""
  94. #############↓网络请求参数↓#################
  95. \(target.baseURL)\(target.path)
  96. \(jsonString?.toHexString() ?? "无参数")
  97. #############↑网络请求参数↑#################
  98. """)
  99. let userinfo = NSKeyedUnarchiver.unarchiveObject(with: userDefault.object(forKey: "userinfo") as! Data ) as! LoginUserInfo
  100. if(userDefault.bool(forKey: "isLogin")){
  101. let bool = userDefault.bool(forKey: "isLogin")
  102. log.info("prepare\(bool)")
  103. let cc = userinfo.cloudcode == nil ? "" : userinfo.cloudcode ?? ""
  104. let id = userinfo.userid == nil ? "" : String(userinfo.userid ?? -1)
  105. let tv = (userinfo.token_value == nil ? "" : userinfo.token_value) ?? ""
  106. let key = "\(cc)_\(id)_p_phone_t"
  107. mRequest.addValue(key, forHTTPHeaderField: "Token_Key")
  108. mRequest.addValue(tv, forHTTPHeaderField: "Token_Value")
  109. }
  110. if let header = mRequest.allHTTPHeaderFields {
  111. log.info("请求头内容\(header)")
  112. }
  113. return mRequest
  114. }
  115. /// Called immediately before a request is sent over the network (or stubbed).(可进行网络等待,loading等)
  116. func willSend(_ request: RequestType, target: TargetType) {
  117. // guard let target = target as? AccountService else { return }
  118. // let jsonData = try? JSONSerialization.data(withJSONObject: target.parameters, options: .prettyPrinted)
  119. // let jsonString = String(data: jsonData ?? Data(), encoding: .utf8)
  120. // print("""
  121. // #############↓网络请求参数↓#################
  122. // \(target.baseURL)\(target.path)
  123. // \(jsonString ?? "无参数")
  124. // #############↑网络请求参数↑#################
  125. // """)
  126. }
  127. /// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.(loading结束等)
  128. func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
  129. }
  130. /// Called to modify a result before completion.(可进行数据解密等)
  131. func process(_ result: Result<Response, MoyaError>, target: TargetType) -> Result<Response, MoyaError> {
  132. return result
  133. }
  134. }
  135. let accountProvider = MoyaProvider<AccountService>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
  136. public class NetworkManaer{
  137. /// 使用Moya的请求封装
  138. ///
  139. /// - Parameters:
  140. /// - target: 请求API,TargetType里的枚举值
  141. /// - success: 成功的回调
  142. /// - error: 连接服务器成功但是数据获取失败
  143. /// - failure: 连接服务器失败
  144. ///
  145. public class func request<T: TargetType,U: HandyJSON>(_ target: T, success: @escaping((U) -> Void), failure: ((Int?, String) ->Void)?) {
  146. let provider = MoyaProvider<T>(
  147. endpointClosure: myEndpointClosure,
  148. requestClosure: requestClosure,
  149. plugins: [networkPlugin,NetworkPlugin.init()],
  150. trackInflights: false
  151. // networkLoggerPlugin
  152. )
  153. provider.request(target) { result in
  154. switch result {
  155. case let .success(response):
  156. // let json = try? response.mapString()
  157. // let responseObject = try? response.mapJSON()
  158. // JhLog( responseObject ?? "" );
  159. do {
  160. // *********** 这里可以统一处理错误码,弹出提示信息 ***********
  161. let resObject = try? response.mapJSON()
  162. log.info("网络请求到的数据是:\(resObject)")
  163. let responseObject = JSON(resObject ?? "")
  164. let code = responseObject["code"].intValue
  165. let msg = String(describing: responseObject["msg"])
  166. switch (code) {
  167. case 0 :
  168. let dictionary=responseObject["obj"].dictionaryObject
  169. let responseData=U.deserialize(from: dictionary)
  170. log.info(responseData?.toJSONString())
  171. // 数据返回正确
  172. success(responseData!)
  173. case 2:
  174. let userDefault=UserDefaults.standard
  175. userDefault.setValue(false, forKey: "isLogin")
  176. // 请重新登录
  177. failure!(code,msg)
  178. alertLogin(msg)
  179. default:
  180. // 其他错误
  181. failureHandle(failure: failure, stateCode: code, message: msg)
  182. }
  183. }
  184. case let .failure(error):
  185. let statusCode = error.response?.statusCode ?? 1000
  186. let message = "请求出错,错误码:" + String(statusCode)
  187. log.error(message)
  188. failureHandle(failure: failure, stateCode: statusCode, message: error.errorDescription ?? message)
  189. }
  190. }
  191. // 错误处理 - 弹出错误信息
  192. func failureHandle(failure: ((Int?, String) ->Void)? , stateCode: Int?, message: String) {
  193. // Alert.show(type: .error, text: message)
  194. //弹出错误信息
  195. failure?(stateCode ,message)
  196. }
  197. // 登录弹窗 - 弹出是否需要登录的窗口
  198. func alertLogin(_ title: String?) {
  199. // TODO: 跳转到登录页的操作:
  200. }
  201. }
  202. // MARK: - 打印日志
  203. // static let networkLoggerPlugin = NetworkLoggerPlugin(verbose: true, cURL: true, requestDataFormatter: { data -> String in
  204. // return String(data: data, encoding: .utf8) ?? ""
  205. // }) { data -> (Data) in
  206. // do {
  207. // let dataAsJSON = try JSONSerialization.jsonObject(with: data)
  208. // let prettyData = try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
  209. // return prettyData
  210. // } catch {
  211. // return data
  212. // }
  213. // }
  214. }