Advertisement
Guest User

Untitled

a guest
Nov 2nd, 2018
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.35 KB | None | 0 0
  1. //
  2. // RestServiceManager.swift
  3. // MSHTTPConnection
  4. //
  5. // Created by Alexandra T. Georgieva on 2/18/16.
  6. // Copyright Β© 2016 Alexandra T. Georgieva. All rights reserved.
  7. //
  8.  
  9. import Foundation
  10.  
  11. public typealias ExpectedResultParameters = (isArray: Bool, type: NSObject.Type, jsonKey: String?)
  12.  
  13.  
  14. /**This class makes the requests to the backend API
  15. Responsibilities:
  16. * takes care of requests configuration - privacy, timeouts, headers etc
  17. * takes care of blocking the UI if requested
  18. * coordinates error handling, caching
  19. * takes care of parsing the response to Swift objects
  20. */
  21. open class RestServiceManager {
  22.  
  23. //MARK:- Singleton
  24.  
  25. private struct Static {
  26. static var instance: RestServiceManager? = nil
  27. }
  28.  
  29. private static var initSelf: (()->())?
  30.  
  31. private static var __once: () = {
  32. initSelf?()
  33. }()
  34.  
  35. static public var sharedInstance: RestServiceManager {
  36. if Static.instance == nil {
  37. initSelf = {
  38. Static.instance = self.init()
  39. }
  40. }
  41. _ = RestServiceManager.__once
  42. return Static.instance!
  43. }
  44.  
  45. ///You probably don't want to use it. Use sharedInstanceInstead
  46. required public init() {
  47.  
  48. }
  49.  
  50. open static var configurator: RestServiceManagerConfiguratorProtocol.Type?
  51.  
  52. //MARK: - Public functions
  53.  
  54. open func basicAuthRequest(username: String,
  55. password: String,
  56. relativeURL: String,
  57. parameters: [String: NSObject]?,
  58. requestType:RequestType,
  59. header: HeaderTypeProtocol,
  60. showActivityIndicator: Bool,
  61. shouldCacheResult: Bool = false,
  62. shouldIgnoreCache: Bool = false,
  63. shouldReceiveUpdates: Bool = false,
  64. clearCacheNotificationNames: [String]? = nil,
  65. cancelNotificationNames: [String]? = nil,
  66. expectedResultType:ExpectedResultParameters? = nil,
  67. successBlock:GeneralSuccessBlock?,
  68. errorBlock:GeneralErrorBlock?) -> Requestor?{
  69.  
  70. let serializer = header.serializer(forRequest: nil)
  71. serializer?.setAuthorizationHeaderFieldWithUsername(username, password: password)
  72.  
  73. return request(relativeURL: relativeURL, parameters: parameters, requestType: requestType, header: header, showActivityIndicator:showActivityIndicator, shouldCacheResult:shouldCacheResult, shouldIgnoreCache:shouldIgnoreCache, shouldReceiveUpdates: shouldReceiveUpdates, clearCacheNotificationNames: clearCacheNotificationNames,
  74. cancelNotificationNames: cancelNotificationNames,expectedResultType: expectedResultType, successBlock: { response in
  75. serializer?.clearAuthorizationHeader()
  76. successBlock?(response)
  77. }, errorBlock: { request, error in
  78. serializer?.clearAuthorizationHeader()
  79. errorBlock?(request, error)
  80. })
  81. }
  82.  
  83.  
  84. /**
  85. If the HTTP method is `GET`, `HEAD`, or `DELETE`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. Otherwise, the parameters will be encoded according to the value of the `parameterEncoding` property, and set as the request body.
  86. */
  87. open func request(relativeURL: String,
  88. parameters: [String: NSObject]?,
  89. httpBody: String? = nil,
  90. requestType:RequestType,
  91. header: HeaderTypeProtocol,
  92. showActivityIndicator: Bool,
  93. shouldCacheResult: Bool = false,
  94. shouldIgnoreCache: Bool = false,
  95. shouldReceiveUpdates: Bool = false,
  96. clearCacheNotificationNames: [String]? = nil,
  97. cancelNotificationNames: [String]? = nil,
  98. expectedResultType:ExpectedResultParameters? = nil,
  99. successBlock:GeneralSuccessBlock?,
  100. errorBlock:GeneralErrorBlock?) -> Requestor?{
  101.  
  102. let request = requestPool.getRequest(url: relativeURL, parameters: parameters,type: requestType, header: header)
  103.  
  104. if let cancelNotificationNames = cancelNotificationNames {
  105. request.addCancelNotificationNames(cancelNotificationNames)
  106. }
  107.  
  108. if let clearCacheNotificationNames = clearCacheNotificationNames {
  109. request.addClearCacheNotificationNames(clearCacheNotificationNames)
  110. }
  111.  
  112. let requestor: Requestor?
  113.  
  114. switch request.state {
  115. case .ready:
  116.  
  117. if shouldIgnoreCache {
  118. fallthrough
  119. }
  120. else if let data = cacheManager?.getCache(forRequest: request) {
  121. successBlock?(data)
  122. if shouldReceiveUpdates {
  123. let requestor = configureRequestorWithSuccess(successBlock, error: nil, forRequest: request, shouldReceiveUpdates: shouldReceiveUpdates)
  124. return requestor
  125. }
  126. return nil
  127. }
  128. else {
  129. fallthrough
  130. }
  131. case .notRequested, .cancelled, .failed:
  132.  
  133. request.state = .downloading
  134. requestor = configureRequestorWithSuccess(successBlock, error: errorBlock, forRequest: request, shouldReceiveUpdates: shouldReceiveUpdates)
  135. requestor!.isInProgress = true
  136. requestor!.shouldShowActivityIndicator = showActivityIndicator
  137.  
  138. case .waiting, .downloading:
  139. let requestor = configureRequestorWithSuccess(successBlock, error: errorBlock, forRequest: request, shouldReceiveUpdates: shouldReceiveUpdates)
  140. requestor.isInProgress = true
  141. requestor.shouldShowActivityIndicator = showActivityIndicator
  142. if !request.isShowingActivityIndicator && requestor.shouldShowActivityIndicator {
  143. LoadingIndicatorManager.sharedInstance.shouldBlockUI()
  144. request.isShowingActivityIndicator = true
  145. }
  146. return requestor
  147. }
  148.  
  149. if let serializer = header.serializer(forRequest: request), request.state != .waiting {
  150. sessionManager.requestSerializer = serializer
  151. }
  152. else {
  153. return nil
  154. }
  155.  
  156. if !request.isShowingActivityIndicator && requestor!.shouldShowActivityIndicator {
  157. LoadingIndicatorManager.sharedInstance.shouldBlockUI()
  158. request.isShowingActivityIndicator = true
  159. }
  160.  
  161. request.shouldImplementDefaultErrorHandling = true
  162. request.countsOnDefaultErrorHandling = false
  163.  
  164.  
  165. if requestType == .get {
  166.  
  167. request.task = sessionManager.get(relativeURL, parameters: parameters, success: {[weak request, weak self] task, result in
  168.  
  169. guard let closureRequest = request else {
  170. return
  171. }
  172.  
  173. self?.requestSuccessBlock(closureRequest, expectedResultType: expectedResultType, shouldCacheData: shouldCacheResult, shouldIgnoreCache: shouldIgnoreCache, task: task, response: result as AnyObject?)
  174.  
  175. }, failure: { [weak request, weak self] task, error in
  176.  
  177. guard let closureRequest = request else {
  178. return
  179. }
  180.  
  181. self?.requestErrorBlock(closureRequest, task: task, error: error as NSError, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  182.  
  183. })
  184. }
  185.  
  186. else if requestType == .post {
  187.  
  188. if httpBody != nil {
  189. var error : NSError?
  190. if let absoluteURL = URL.init(string: relativeURL, relativeTo: self.sessionManager.baseURL)?.absoluteString {
  191. let urlRequest = self.sessionManager.requestSerializer.request(withMethod: "POST", urlString:absoluteURL , parameters: nil, error: &error)
  192. if error != nil {
  193. self.requestErrorBlock(request, task: nil, error: error!, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  194. }
  195. else {
  196. urlRequest.httpBody = httpBody?.data(using: String.Encoding.utf8)
  197. let dataTask = self.sessionManager.dataTask(with: urlRequest as URLRequest, completionHandler: { [weak request, weak self] urlResponse, response, error in
  198.  
  199. guard let closureRequest = request else {
  200. return
  201. }
  202.  
  203. if error != nil {
  204. self?.requestErrorBlock(closureRequest, task: closureRequest.task, error: error! as NSError, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  205. }
  206. else {
  207. self?.requestSuccessBlock(closureRequest, expectedResultType: expectedResultType, shouldCacheData: shouldCacheResult, shouldIgnoreCache: shouldIgnoreCache, task: closureRequest.task, response: response as AnyObject?)
  208. }
  209. })
  210. request.task = dataTask;
  211. dataTask.resume()
  212. }
  213. }
  214. else {
  215. self.requestErrorBlock(request, task: nil, error: NSError(domain: "RestServiceManager", code: 0, userInfo: nil), expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  216. }
  217. }
  218. else {
  219. request.task = sessionManager.post(relativeURL, parameters: parameters, success: { [weak request, weak self] task, result in
  220. guard let closureRequest = request else {
  221. return
  222. }
  223.  
  224. self?.requestSuccessBlock(closureRequest, expectedResultType: expectedResultType, shouldCacheData: shouldCacheResult, shouldIgnoreCache: shouldIgnoreCache, task: task, response: result as AnyObject?)
  225.  
  226. }, failure: { [weak request, weak self] task, error in
  227. guard let closureRequest = request else {
  228. return
  229. }
  230.  
  231. self?.requestErrorBlock(closureRequest, task: task, error: error as NSError, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  232.  
  233. })
  234. }
  235. }
  236. else if requestType == .delete{
  237. request.task = sessionManager.delete(relativeURL, parameters: parameters, success: { [weak request, weak self] task, result in
  238. guard let closureRequest = request else {
  239. return
  240. }
  241.  
  242. self?.requestSuccessBlock(closureRequest, expectedResultType: expectedResultType, shouldCacheData: shouldCacheResult, shouldIgnoreCache: shouldIgnoreCache, task: task, response: result as AnyObject?)
  243.  
  244. }, failure:{ [weak request, weak self] task, error in
  245. guard let closureRequest = request else {
  246. return
  247. }
  248.  
  249. self?.requestErrorBlock(closureRequest, task: task, error: error as NSError, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  250. })
  251. }
  252.  
  253. return requestor
  254. }
  255.  
  256. open func requestSuccessBlock(_ request: Request, expectedResultType:ExpectedResultParameters?, shouldCacheData: Bool, shouldIgnoreCache: Bool, task: URLSessionDataTask?, response:AnyObject?){
  257.  
  258. //parsing the result
  259. let result = type(of: self).parseResponse(response, expectedResultType: expectedResultType)
  260. if result == nil {
  261. request.state = .failed
  262. requestFinishedWithError(request, error: errorHandler.errorForParsingProblem, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  263. return
  264. }
  265.  
  266. if shouldCacheData {
  267. request.state = .ready
  268. cacheManager?.setCache(forRequest: request, data: cacheManager?.isUsingRawDataForCache == true ? response : result)
  269. }
  270. else {
  271. request.state = .notRequested
  272. }
  273.  
  274. if request.isShowingActivityIndicator {
  275. LoadingIndicatorManager.sharedInstance.shouldUnblockUI()
  276. request.isShowingActivityIndicator = false
  277. }
  278.  
  279.  
  280. request.performSuccessBlocksWithResponse(result)
  281.  
  282. request.task = nil
  283. }
  284.  
  285. open func requestErrorBlock(_ request: Request, task: URLSessionDataTask?, error: NSError, expectedResultType: ExpectedResultParameters?, shouldIgnoreCache: Bool){
  286.  
  287. let err: ServerErrorProtocol
  288.  
  289. //parsing the result
  290. if request.state == .cancelled {
  291. err = errorHandler.errorForCancelation
  292. }
  293. else {
  294. request.state = .failed
  295. if let response = task?.response as? HTTPURLResponse {
  296. err = errorHandler.error(forResponse: response, error: error)
  297. }
  298. else {
  299. err = errorHandler.errorForInternetProblem
  300. }
  301. }
  302.  
  303. requestFinishedWithError(request, error: err, expectedResultType:expectedResultType, shouldIgnoreCache: shouldIgnoreCache)
  304. }
  305.  
  306. open class func parseResponse(_ response:AnyObject?, expectedResultType:ExpectedResultParameters?)-> AnyObject?{
  307. if let expectedResultType = expectedResultType {
  308. var result: NSObject?
  309. if expectedResultType.isArray {
  310. if let jsonKey = expectedResultType.jsonKey,
  311. let dict = response as? [String: AnyObject]{
  312. if let jsonArray = dict[jsonKey] as? [AnyObject]{
  313. if let mappedArray = JSONMapper.JSONMapWithArray(jsonArray, forClass: expectedResultType.type){
  314. result = mappedArray as NSObject?
  315. }
  316. }
  317. else {
  318. return [NSObject]() as AnyObject?
  319. }
  320. }
  321. else if let jsonArray = result as? [AnyObject],
  322. let mappedArray = JSONMapper.JSONMapWithArray(jsonArray, forClass: expectedResultType.type){
  323. result = mappedArray as NSObject?
  324. }
  325. }
  326. else {
  327. if let jsonKey = expectedResultType.jsonKey,
  328. let dict = response as? [String: AnyObject],
  329. let jsonDict = dict[jsonKey] as? [String: AnyObject]{
  330. result = JSONMapper.JSONMapWithDictionary(jsonDict, forClass: expectedResultType.type)
  331. }
  332. else if let jsonDict = response as? [String: AnyObject]{
  333. result = JSONMapper.JSONMapWithDictionary(jsonDict, forClass: expectedResultType.type)
  334. }
  335. }
  336.  
  337. return result
  338. }
  339.  
  340. return response
  341. }
  342.  
  343. open func requestFinishedWithError(_ request: Request, error: ServerErrorProtocol, expectedResultType: ExpectedResultParameters?, shouldIgnoreCache: Bool){
  344.  
  345. if request.isShowingActivityIndicator {
  346. LoadingIndicatorManager.sharedInstance.shouldUnblockUI()
  347. request.isShowingActivityIndicator = false
  348. }
  349.  
  350.  
  351. request.performErrorBlocksWithError(error)
  352.  
  353. if request.parameters?.keys.contains("Operation") ?? false{
  354. if let value = request.parameters?["Operation"]{
  355. if ["getSmartSharing", "getMbbEligibility"].contains(value as! String) {
  356. request.task = nil
  357. return
  358. }
  359. }
  360.  
  361. }
  362.  
  363.  
  364. if request.shouldImplementDefaultErrorHandling || request.countsOnDefaultErrorHandling {
  365. errorHandler.sharedInstance.handleError(error)
  366. }
  367.  
  368. request.task = nil
  369. }
  370.  
  371. open func configureRequestorWithSuccess(_ success: GeneralSuccessBlock?, error: GeneralErrorBlock?, forRequest request: Request, shouldReceiveUpdates: Bool) -> Requestor {
  372. let requestor = Requestor(success: success, error: error)
  373. requestor.request = request
  374. requestor.shouldReceiveUpdates = shouldReceiveUpdates
  375. request.addRequestor(requestor)
  376. return requestor
  377. }
  378.  
  379. open let sessionManager: AFHTTPSessionManager = {
  380.  
  381. let configuration = URLSessionConfiguration.ephemeral
  382. configuration.timeoutIntervalForRequest = configurator!.timeoutTime
  383. //For security reasons no cache is allowed
  384. configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: "")
  385.  
  386. let sessionManager = AFHTTPSessionManager(baseURL: URL(string: configurator!.baseURL), sessionConfiguration: configuration)
  387. sessionManager.responseSerializer = AFJSONResponseSerializer()
  388. sessionManager.requestSerializer = AFJSONRequestSerializer()
  389.  
  390. return sessionManager
  391. }()
  392.  
  393.  
  394. //MARK: - Private
  395. private let requestPool = configurator!.requestPoolType.sharedInstance
  396.  
  397. private let cacheManager = configurator!.cacheManagerType?.sharedInstance
  398.  
  399. private let errorHandler = configurator!.errorHandlerClass
  400.  
  401. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement