SwiftMoyaNetWorkManager.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. //
  2. // SwiftMoyaNetWorkManager.swift
  3. // RainbowPlanet
  4. //
  5. // Created by 南鑫林 on 2018/8/7.
  6. // Copyright © 2018年 南鑫林. All rights reserved.
  7. //
  8. import Foundation
  9. import Alamofire
  10. import Moya
  11. import SwiftyJSON
  12. import ObjectMapper
  13. import RxSwift
  14. import RxCocoa
  15. import Result
  16. /// 超时时长
  17. private var requestTimeOut:Double = 10
  18. ///网络请求的基本设置,这里可以拿到是具体的哪个网络请求,可以在这里做一些设置
  19. private let myEndpointClosure = { (target: MultiTarget) -> Endpoint in
  20. ///这里把endpoint重新构造一遍主要为了解决网络请求地址里面含有? 时无法解析的bug https://github.com/Moya/Moya/issues/1198
  21. let url = target.baseURL.absoluteString + target.path
  22. var task = target.task
  23. /*
  24. 👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆
  25. 如果需要在每个请求中都添加类似token参数的参数请取消注释上面代码
  26. */
  27. var endpoint = Endpoint(
  28. url: url,
  29. sampleResponseClosure: { .networkResponse(200, target.sampleData) },
  30. method: target.method,
  31. task: task,
  32. httpHeaderFields: target.headers
  33. )
  34. requestTimeOut = 10//每次请求都会调用endpointClosure 到这里设置超时时长 也可单独每个接口设置
  35. return endpoint
  36. }
  37. ///网络请求的设置
  38. private let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
  39. do {
  40. var request = try endpoint.urlRequest()
  41. //设置请求时长
  42. request.timeoutInterval = requestTimeOut
  43. // 打印请求参数
  44. if let requestData = request.httpBody {
  45. let parameter = "\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")"
  46. NXLLog("\n"+"请求地址:"+"\(request.url!)"+"\n"+"请求方式:"+"\(request.httpMethod ?? "")"+"\n"+"请求头部:"+"\(String(describing: request.allHTTPHeaderFields!))"+"\n"+"发送参数:" + String(describing: parameter.removingPercentEncoding!))
  47. }else{
  48. let urlStr = "\(request.url!)"
  49. NXLLog("\n"+"请求地址:"+String(describing: urlStr.removingPercentEncoding!)+"\n"+"请求方式:"+"=\(String(describing: request.httpMethod!))"+"\n"+"请求头部:"+"\(String(describing: request.allHTTPHeaderFields!))")
  50. }
  51. done(.success(request))
  52. } catch {
  53. done(.failure(MoyaError.underlying(error, nil)))
  54. }
  55. }
  56. /// NetworkActivityPlugin插件用来监听网络请求,界面上做相应的展示
  57. ///但这里我没怎么用这个。。。 loading的逻辑直接放在网络处理里面了
  58. private let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
  59. print("networkPlugin \(changeType)")
  60. //targetType 是当前请求的基本信息
  61. switch(changeType){
  62. case .began:
  63. DispatchQueue.main.async(execute: { () -> Void in
  64. UIApplication.shared.isNetworkActivityIndicatorVisible = true
  65. })
  66. case .ended:
  67. DispatchQueue.main.async(execute: { () -> Void in
  68. UIApplication.shared.isNetworkActivityIndicatorVisible = false
  69. })
  70. }
  71. }
  72. private let provider = MoyaProvider<MultiTarget>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
  73. /// 基于Alamofire,网络是否连接,,这个方法不建议放到这个类中,可以放在全局的工具类中判断网络链接情况
  74. /// 用get方法是因为这样才会在获取isNetworkConnect时实时判断网络链接请求,如有更好的方法可以fork
  75. private var isNetworkConnect: Bool {
  76. get{
  77. let network = NetworkReachabilityManager()
  78. return network?.isReachable ?? true //无返回就默认网络已连接
  79. }
  80. }
  81. public class SwiftMoyaNetWorkManager: NSObject {
  82. private let disposeBag = DisposeBag()
  83. private var dataBaseName : String = "RainbowPlanet"
  84. private static let _sharedInstance = SwiftMoyaNetWorkManager()
  85. private override init() {} // 私有化init方法
  86. /// 获取单例
  87. ///
  88. /// - Returns: SwiftMoyaNetWorkManager对象
  89. class func shared() -> SwiftMoyaNetWorkManager {
  90. return _sharedInstance
  91. }
  92. /// 成功回调
  93. typealias successCallback = (_ data: Any) -> Void
  94. /// 成功回调带泛型
  95. typealias successCallTBack = (_ T: BaseMappable) -> Void
  96. typealias successCallArrayTback = (_ T: [BaseMappable]) -> Void
  97. typealias falseCallback = () -> Void
  98. var falseCallback : falseCallback?
  99. /// 网络请求
  100. ///
  101. /// - Parameters:
  102. /// - type: 模型
  103. /// - target: 请求地址加参数
  104. /// - isCache: 是否缓存
  105. /// - completion: 回调
  106. func request<T: BaseMappable>(_ type: T.Type ,target: MultiTarget,isCustomAlert:Bool = false,completion: @escaping successCallTBack) -> Void {
  107. //判断是否链接网络
  108. if !isNetworkConnect{
  109. SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  110. return
  111. }
  112. provider.rx
  113. .request(target)
  114. .map(T.self)
  115. .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
  116. .observeOn(MainScheduler.instance)
  117. .subscribe(onSuccess: { [weak self] element in
  118. guard let element = element else {
  119. if let falseCallback = self?.falseCallback {
  120. falseCallback()
  121. }
  122. return
  123. }
  124. completion(element)
  125. }) {
  126. [weak self] (error) in
  127. if let falseCallback = self?.falseCallback {
  128. falseCallback()
  129. }
  130. SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  131. }
  132. .disposed(by: disposeBag)
  133. }
  134. /// 网络请求
  135. ///
  136. /// - Parameters:
  137. /// - type: 模型
  138. /// - target: 请求地址加参数
  139. /// - isCache: 是否缓存
  140. /// - completion: 回调
  141. func requestArray<T: BaseMappable>(_ type: T.Type ,target: MultiTarget,isCustomAlert:Bool = false,completion: @escaping successCallArrayTback) -> Void {
  142. //判断是否链接网络
  143. if !isNetworkConnect{
  144. SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  145. return
  146. }
  147. provider.rx
  148. .request(target)
  149. .mapArray(T.self)
  150. .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
  151. .observeOn(MainScheduler.instance)
  152. .subscribe(onSuccess: { [weak self] element in
  153. guard let element = element else {
  154. if let falseCallback = self?.falseCallback {
  155. falseCallback()
  156. }
  157. return
  158. }
  159. completion(element)
  160. }) {
  161. [weak self] (error) in
  162. if let falseCallback = self?.falseCallback {
  163. falseCallback()
  164. }
  165. SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  166. }
  167. .disposed(by: disposeBag)
  168. }
  169. /// 缓存请求
  170. ///
  171. /// - Parameters:
  172. /// - target: 请求地址加参数
  173. /// - alwaysFetchCache: 是否总是缓存
  174. /// - cacheType: 缓存类型
  175. /// - completion: 请求成功回调
  176. // func cacheRequest<T: BaseMappable>(_ type: T.Type,target: MultiTarget,isCustomAlert:Bool = false,alwaysFetchCache: Bool = false,cacheType: MMCache.CacheKeyType = .default,completion: @escaping successCallback) -> Void {
  177. //
  178. // //判断是否链接网络
  179. // if !isNetworkConnect{
  180. // SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  181. // return
  182. // }
  183. // var cacheResponse: Response? = nil
  184. // if alwaysFetchCache {
  185. // cacheResponse = MMCache.shared.fetchResponseCache(target: target)
  186. // self.getResponseStatusCode(response: cacheResponse!, isCustomAlert: isCustomAlert, completion: completion)
  187. // } else {
  188. // if MMCache.shared.isNoRecord(target, cacheType: cacheType) {
  189. // MMCache.shared.record(target)
  190. // cacheResponse = MMCache.shared.fetchResponseCache(target: target)
  191. // self.getResponseStatusCode(response: cacheResponse!, isCustomAlert: isCustomAlert, completion: completion)
  192. // }
  193. // }
  194. // provider.rx
  195. // .request(target)
  196. // .map(T.self)
  197. // .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
  198. // .observeOn(MainScheduler.instance)
  199. // .subscribe(onSuccess: { [weak self] response in
  200. // MMCache.shared.cacheResponse(response as! Response, target: target)
  201. // self?.getResponseStatusCode(response: response as! Response, isCustomAlert: isCustomAlert, completion: completion)
  202. // }) {
  203. // [weak self] (error) in
  204. // if let falseCallback = self?.falseCallback {
  205. // falseCallback()
  206. // }
  207. // SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  208. // }
  209. // .disposed(by: disposeBag)
  210. //
  211. // }
  212. // MARK: - 网络请求
  213. /// 网络请求
  214. ///
  215. /// - Parameters:
  216. /// - target: 请求地址加参数
  217. /// - completion: 请求成功回调
  218. func request(target: MultiTarget,isCustomAlert:Bool = false,completion: @escaping successCallback) -> Void {
  219. //判断是否链接网络
  220. if !isNetworkConnect{
  221. SwiftProgressHUD.shared().showText("网络链接失败,请检查网络")
  222. return
  223. }
  224. provider.rx
  225. .request(target)
  226. .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
  227. .observeOn(MainScheduler.instance)
  228. .subscribe(onSuccess: { [weak self] response in
  229. self?.getResponseStatusCode(response: response, isCustomAlert: isCustomAlert, completion: completion)
  230. }) {
  231. [weak self] (error) in
  232. SwiftProgressHUD.shared().showText(error.localizedDescription)
  233. if let falseCallback = self?.falseCallback {
  234. falseCallback()
  235. }
  236. }
  237. .disposed(by: disposeBag)
  238. }
  239. /// 缓存请求
  240. ///
  241. /// - Parameters:
  242. /// - target: 请求地址加参数
  243. /// - alwaysFetchCache: 是否总是缓存
  244. /// - cacheType: 缓存类型
  245. /// - completion: 请求成功回调
  246. // func cacheRequest(target: MultiTarget,isCustomAlert:Bool = false,alwaysFetchCache: Bool = false,cacheType: MMCache.CacheKeyType = .default,completion: @escaping successCallback) -> Void {
  247. //
  248. // //判断是否链接网络
  249. // if !isNetworkConnect{
  250. // SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  251. // return
  252. // }
  253. // var cacheResponse: Response? = nil
  254. // if alwaysFetchCache {
  255. // cacheResponse = MMCache.shared.fetchResponseCache(target: target)
  256. // self.getResponseStatusCode(response: cacheResponse!, isCustomAlert: isCustomAlert, completion: completion)
  257. // } else {
  258. // if MMCache.shared.isNoRecord(target, cacheType: cacheType) {
  259. // MMCache.shared.record(target)
  260. // cacheResponse = MMCache.shared.fetchResponseCache(target: target)
  261. // self.getResponseStatusCode(response: cacheResponse!, isCustomAlert: isCustomAlert, completion: completion)
  262. // }
  263. // }
  264. // provider.rx
  265. // .request(target)
  266. // .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
  267. // .observeOn(MainScheduler.instance)
  268. // .subscribe(onSuccess: { [weak self] response in
  269. // MMCache.shared.cacheResponse(response, target: target)
  270. // self?.getResponseStatusCode(response: response, isCustomAlert: isCustomAlert, completion: completion)
  271. // }) {
  272. // [weak self] (error) in
  273. // if let falseCallback = self?.falseCallback {
  274. // falseCallback()
  275. // }
  276. // SwiftProgressHUD.shared().showError("网络链接失败,请检查网络")
  277. // }
  278. // .disposed(by: disposeBag)
  279. //
  280. // }
  281. // MARK: - 获取状态码
  282. /// 获取状态码
  283. ///
  284. /// - Parameters:
  285. /// - response: 响应结果
  286. /// - completion: 回调
  287. private func getResponseStatusCode(response:Response, isCustomAlert:Bool , completion: @escaping successCallback) -> Void {
  288. let json = try? JSON(response.mapJSON())
  289. if response.statusCode == 200 {
  290. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json!.description)");
  291. let json = JSON(parseJSON: json!.description)
  292. let rootModel = RootModel(JSONString: json.description)
  293. let data = JSON(json["data"]).description
  294. rootModel?.data = data
  295. if rootModel!.code == 0 {
  296. completion(rootModel as Any)
  297. }else if rootModel!.code == 1 {
  298. if !isCustomAlert {
  299. SwiftProgressHUD.shared().showText(rootModel!.msg ?? "信息有误!!!", textAlignment: .left)
  300. }
  301. if let falseCallback = self.falseCallback {
  302. falseCallback()
  303. }
  304. }else {
  305. SwiftProgressHUD.shared().showError(rootModel!.msg ?? "信息有误!!!")
  306. if let falseCallback = self.falseCallback {
  307. falseCallback()
  308. }
  309. }
  310. }else if response.statusCode == 401 {
  311. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json!.description)");
  312. let infoModel = InfoModel(JSONString: json?.description ?? "")
  313. kAppDelegate.setLoginController()
  314. SwiftProgressHUD.shared().showText(infoModel!.message ?? "登录过期,请重新登录")
  315. if let falseCallback = self.falseCallback {
  316. falseCallback()
  317. }
  318. } else {
  319. NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  320. SwiftProgressHUD.shared().showText(response.description)
  321. if let falseCallback = self.falseCallback {
  322. falseCallback()
  323. }
  324. }
  325. }
  326. // MARK: - 取消所有请求
  327. /// 取消所有请求
  328. func cancelAllRequest() {
  329. provider.manager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
  330. dataTasks.forEach { $0.cancel() }
  331. uploadTasks.forEach { $0.cancel() }
  332. downloadTasks.forEach { $0.cancel() }
  333. }
  334. }
  335. // MARK: - 取消指定请求
  336. /// 取消指定请求
  337. ///
  338. /// - Parameter url: 指定的网络请求地址
  339. func cancelDesignationRequest(url:String) {
  340. provider.manager.session.getTasksWithCompletionHandler {
  341. (sessionDataTask, uploadData, downloadData) in
  342. sessionDataTask.forEach {
  343. //只取消指定url的请求
  344. if ($0.originalRequest?.url?.absoluteString == url) {
  345. $0.cancel()
  346. }
  347. }
  348. }
  349. }
  350. }
  351. // MARK: - 泛型返回
  352. extension PrimitiveSequence where TraitType == SingleTrait, ElementType == Response {
  353. func map<T: BaseMappable>(_ type: T.Type) -> Single<T?> {
  354. return flatMap { response -> Single<T?> in
  355. do {
  356. let json = try JSON(response.mapJSON())
  357. if response.statusCode == 200 {
  358. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json.description)");
  359. let json = JSON(parseJSON: json.description)
  360. let rootModel = RootModel(JSONString: json.description)
  361. let data = JSON(json["data"]).description
  362. rootModel?.data = data
  363. if rootModel!.code == 0 {
  364. let mapper = T(JSONString: rootModel!.data ?? "")
  365. return Single<T?>.just(mapper)
  366. }else if rootModel!.code == 1 {
  367. SwiftProgressHUD.shared().showText(rootModel!.msg ?? "信息有误!!!", textAlignment: .left)
  368. return Single<T?>.just(nil)
  369. }else {
  370. NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  371. SwiftProgressHUD.shared().showText(response.description)
  372. return Single<T?>.just(nil)
  373. }
  374. }else if response.statusCode == 401 {
  375. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json.description)");
  376. let infoModel = InfoModel(JSONString: json.description)
  377. SwiftProgressHUD.shared().showText(infoModel!.message ?? "登录过期,请重新登录")
  378. kAppDelegate.setLoginController()
  379. return Single<T?>.just(nil)
  380. }else { NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  381. SwiftProgressHUD.shared().showText(response.description)
  382. return Single<T?>.just(nil)
  383. }
  384. } catch {
  385. NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  386. SwiftProgressHUD.shared().showText(response.description)
  387. return Single<T?>.just(nil)
  388. }
  389. }
  390. }
  391. func mapArray<T: BaseMappable>(_ type: T.Type) -> Single<[T]?> {
  392. return flatMap { response -> Single<[T]?> in
  393. do {
  394. let json = try JSON(response.mapJSON())
  395. if response.statusCode == 200 {
  396. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json.description)");
  397. let json = JSON(parseJSON: json.description)
  398. let rootModel = RootModel(JSONString: json.description)
  399. let data = JSON(json["data"]).description
  400. rootModel?.data = data
  401. if rootModel!.code == 0 {
  402. let mapper = Mapper<T>().mapArray(JSONString: rootModel!.data!)
  403. return Single<[T]?>.just(mapper)
  404. }else if rootModel!.code == 1 {
  405. SwiftProgressHUD.shared().showText(rootModel!.msg ?? "信息有误!!!", textAlignment: .left)
  406. return Single<[T]?>.just(nil)
  407. }else {
  408. NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  409. SwiftProgressHUD.shared().showText(response.description)
  410. return Single<[T]?>.just(nil)
  411. }
  412. }else if response.statusCode == 401 {
  413. NXLLog("\nstatusCode=\(response.statusCode)\njson=\n\(json.description)");
  414. let infoModel = InfoModel(JSONString: json.description)
  415. SwiftProgressHUD.shared().showText(infoModel!.message ?? "登录过期,请重新登录")
  416. kAppDelegate.setLoginController()
  417. return Single<[T]?>.just(nil)
  418. }else { NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  419. SwiftProgressHUD.shared().showText(response.description)
  420. return Single<[T]?>.just(nil)
  421. }
  422. } catch {
  423. NXLLog("\nstatusCode=\(response.statusCode)\nerror=\n\(response.description)");
  424. SwiftProgressHUD.shared().showText(response.description)
  425. return Single<[T]?>.just(nil)
  426. }
  427. }
  428. }
  429. }