Skip to content

Instantly share code, notes, and snippets.

@1hakr
Created July 6, 2018 06:47
Show Gist options
  • Save 1hakr/6e7efcd72a0fa5d5dbebc3ab62972d3c to your computer and use it in GitHub Desktop.
Save 1hakr/6e7efcd72a0fa5d5dbebc3ab62972d3c to your computer and use it in GitHub Desktop.
Network Helper for iOS with custom caching and bootstrapping suppory
//
// NetworkHelper.swift
// acrypto
//
// Created by HaKr on 21/10/17.
// Copyright © 2017 DWorkS. All rights reserved.
//
import Foundation
import Alamofire
public protocol NetworkCompletionDelegate {
func onResponse(_ response: Any)
func onErrorResponse(_ error: Error)
}
class NetworkHelper: NSObject {
static var sessionManager: SessionManager!
static var sessionConfiguration: URLSessionConfiguration!
static var sessionManagerMaster: SessionManager!
static var sessionConfigurationMaster: URLSessionConfiguration!
static func getSessionManger() -> SessionManager {
if(nil == sessionManager) {
let capacity = 50 * 1024 * 1024 // MBs
let urlCache = SmartUrlCache(memoryCapacity: capacity, diskCapacity: capacity, diskPath: nil)
sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.requestCachePolicy = .returnCacheDataElseLoad
sessionConfiguration.urlCache = urlCache
sessionConfiguration.timeoutIntervalForRequest = 10
sessionManager = Alamofire.SessionManager(configuration: sessionConfiguration)
}
return sessionManager
}
static func getSessionMangerMaster() -> SessionManager {
if(nil == sessionManagerMaster) {
let capacity = 50 * 1024 * 1024 // MBs
let urlCache = SmartUrlMasterCache(memoryCapacity: capacity, diskCapacity: capacity, diskPath: nil)
sessionConfigurationMaster = URLSessionConfiguration.default
sessionConfigurationMaster.requestCachePolicy = .returnCacheDataElseLoad
sessionConfigurationMaster.urlCache = urlCache
sessionManagerMaster = Alamofire.SessionManager(configuration: sessionConfigurationMaster)
}
return sessionManagerMaster
}
static func removeCachedUrl(url: String, parameters: Parameters? = nil) {
let headers: HTTPHeaders? = nil
var originalRequest: URLRequest
do {
originalRequest = try URLRequest(url: url, method: .get, headers: headers)
let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters)
sessionConfiguration.urlCache?.removeCachedResponse(for: encodedURLRequest)
addCache(url: url, data: Data(), parameters: parameters)
} catch {
Log.info(error)
}
}
static func removeMasterCachedUrl(url: String, parameters: Parameters? = nil) {
let headers: HTTPHeaders? = nil
var originalRequest: URLRequest
do {
originalRequest = try URLRequest(url: url, method: .get, headers: headers)
let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters)
sessionConfiguration.urlCache?.removeCachedResponse(for: encodedURLRequest)
addMasterCache(url: url, data: Data(), parameters: parameters)
} catch {
Log.info(error)
}
}
static func removeAllCached() {
sessionConfigurationMaster.urlCache?.removeAllCachedResponses()
}
static func addCache(url: String, data: Data, parameters: Parameters? = nil) {
let headers: HTTPHeaders? = nil
do {
let originalRequest = try URLRequest(url: url, method: .get, headers: headers)
let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters)
let newResponse = HTTPURLResponse(url: URL(string: url)!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Cache-Control":"private, max-age=0, s-maxage=0"])
let cachedResponse = CachedURLResponse(response: newResponse!, data: data)
sessionConfiguration.urlCache?.storeCachedResponse(cachedResponse, for: encodedURLRequest)
} catch {
Log.info(error)
}
}
static func addMasterCache(url: String, data: Data, parameters: Parameters? = nil) {
let headers: HTTPHeaders? = nil
do {
let originalRequest = try URLRequest(url: url, method: .get, headers: headers)
let encodedURLRequest = try URLEncoding.default.encode(originalRequest, with: parameters)
let newResponse = HTTPURLResponse(url: URL(string: url)!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Cache-Control":"private, max-age=0, s-maxage=0"])
let cachedResponse = CachedURLResponse(response: newResponse!, data: data)
sessionConfigurationMaster.urlCache?.storeCachedResponse(cachedResponse, for: encodedURLRequest)
} catch {
Log.info(error)
}
}
static func requestJSON(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){
getSessionManger().request(url, method: .get, parameters: parameters)
.validate()
.responseJSON { response in
switch response.result {
case .success:
Log.info("Request: \(String(describing: response.request))")
completionDelegate.onResponse(response)
break
case .failure(let error):
Log.info("Error: \(error)")
completionDelegate.onErrorResponse(error)
}
}
}
static func requestJSON(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse<Any>) -> Void) {
getSessionManger().request(url, method: .get, parameters: parameters).validate().responseJSON(completionHandler: completionHandler)
}
static func requestString(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){
getSessionManger().request(url, method: .get, parameters: parameters)
.validate()
.responseString { response in
switch response.result {
case .success:
Log.info("Request: \(String(describing: response.request))")
completionDelegate.onResponse(response)
break
case .failure(let error):
Log.info("Error: \(error)")
completionDelegate.onErrorResponse(error)
}
}
}
static func requestString(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse<String>) -> Void) {
getSessionManger().request(url, method: .get, parameters: parameters).validate().responseString(completionHandler: completionHandler)
}
static func requestJSONMaster(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){
getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders())
.validate()
.responseJSON { response in
switch response.result {
case .success:
Log.info("Request: \(String(describing: response.request))")
completionDelegate.onResponse(response)
break
case .failure(let error):
Log.info("Error: \(error)")
completionDelegate.onErrorResponse(error)
}
}
}
static func requestJSONMaster(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse<Any>) -> Void) {
getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()).validate().responseJSON(completionHandler: completionHandler)
}
static func requestStringMaster(_ url: String, _ parameters: Parameters, _ completionDelegate: NetworkCompletionDelegate){
getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders())
.validate()
.responseString { response in
switch response.result {
case .success:
Log.info("Request: \(String(describing: response.request))")
completionDelegate.onResponse(response)
break
case .failure(let error):
Log.info("Error: \(error)")
completionDelegate.onErrorResponse(error)
}
}
}
static func requestStringMaster(_ url: String, _ parameters: Parameters, _ completionHandler: @escaping (DataResponse<String>) -> Void) {
getSessionMangerMaster().request(url, method: .get, parameters: parameters, headers: getHeaders()).validate().responseString(completionHandler: completionHandler)
}
static func getHeaders() -> HTTPHeaders{
var headers: HTTPHeaders = [:]
headers.updateValue(Constants.AUTH, forKey: Constants.AUTH_HEADER)
headers.updateValue(AppHelper.versionName ?? "", forKey: Constants.CLIENT_HEADER)
return headers
}
}
class SmartUrlCache: URLCache {
let CACHE_EXPIRY = "cache_expiry";
let cacheExpireInterval: TimeInterval = 60*60;
override func cachedResponse(for request: URLRequest) -> CachedURLResponse? {
var response: CachedURLResponse? = nil
if let cachedResponse = super.cachedResponse(for: request) {
if let userInfo = cachedResponse.userInfo {
if let cacheDate = userInfo[CACHE_EXPIRY] as! NSDate? {
// check if the cache data are expired
let count = cachedResponse.data.count
if (cacheDate.timeIntervalSinceNow < -cacheExpireInterval) || count == 0 {
self.removeCachedResponse(for: request)
} else {
response = cachedResponse
}
}
}
}
return response;
}
override func removeCachedResponse(for request: URLRequest) {
super.removeCachedResponse(for: request)
}
override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) {
var userInfo = NSMutableDictionary()
if let cachedUserInfo = cachedResponse.userInfo {
userInfo = NSMutableDictionary(dictionary: cachedUserInfo)
}
if let cacheDate = userInfo[CACHE_EXPIRY] as! NSDate? {
// check if the cache data are expired
if (cacheDate.timeIntervalSinceNow < -cacheExpireInterval) {
userInfo[CACHE_EXPIRY] = NSDate()
}
} else {
userInfo[CACHE_EXPIRY] = NSDate()
}
let newCachedResponse = CachedURLResponse(response: cachedResponse.response, data: cachedResponse.data, userInfo: userInfo as [NSObject : AnyObject], storagePolicy: cachedResponse.storagePolicy)
super.storeCachedResponse(newCachedResponse, for: request)
}
}
class SmartUrlMasterCache: URLCache {
override func cachedResponse(for request: URLRequest) -> CachedURLResponse? {
var response: CachedURLResponse? = nil
if let cachedResponse = super.cachedResponse(for: request) {
let count = cachedResponse.data.count
if count == 0 {
self.removeCachedResponse(for: request)
} else {
response = cachedResponse
}
}
return response;
}
override func removeCachedResponse(for request: URLRequest) {
super.removeCachedResponse(for: request)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment