Secondary packaging of Alamofire
Recently, I began to learn Swift. Among the selection of network tools, I chose AFNetworking’s Swift version –>Alamofire. In order to facilitate the development of the project, I made some encapsulation of Alamofire, without saying too much and directly loading codes
Utility class property definition
// Network request Keylet BWRequestMethodKey = "BWRequestMethodKey"Typealias BWNetworkSuccess = (_ isSuccess: Bool, _ code: String, _ hint: String, _ list:) typeAlias BWNetworkSuccess = (_ isSuccess: Bool, _ code: String, _ hint: String, _ list: AnyObject, _ responseData: AnyObject) -> Void // Network request failed callback TypeAlias BWNetworkFail = (_ error: AnyObject) -> Void // Network statusTypeAlias BWNetworkStatusBlock = (_ networkStatus: UInt32) -> Void enum BWNetworkStatus: Int32 {caseUnkonw = -1 // Unknown networkcaseNotReachable = 0 // No network connectioncaseWwan = 1 //2, 3, 4G networkcaseWifi = 2 //wifi} class BWNetworkingService: NSObject {//MARK: var &let
static letShareService = BWNetworkingService() // Records the current request route. Private var currentRequestUrl: String =""Private var currentRequestMethod: HTTPMethod =. Get // Record the current request interface parameters. Private var currentParams: Dictionary<String,Any>? // Record whether the current interface needs to be cached locally. Private var shouldCache: Bool =false// Timeout duration privateletRequestTimeout: TimeInterval = 20 // Timeout period for obtaining resources privatelet resourceTimeout: TimeInterval = 20
//header
private lazy var httpHeader: [String: Any] = {
let header : HTTPHeaders = SessionManager.defaultHTTPHeaders
// header["Authorization"] = ""
// header.updateValue("application/json".forKey: "Accept")
returnHeader}() // Data cache path privatelet cachePath = NSHomeDirectory() + "/Documents/NetworkingCaches/"// current networkStatus private var networkStatus: BWNetworkStatus =. Wifi //sessionManager private lazy var sessionManager: SessionManager = {#warning(" Cancel error will be reported on the first request processed by another SessionManager in the task group, temporarily changed to default, will be processed later ")
return SessionManager.default
// let configuration = URLSessionConfiguration.default
// configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
// configuration.timeoutIntervalForRequest = self.requestTimeout
// configuration.timeoutIntervalForResource = self.resourceTimeout
// return SessionManager(configuration: configuration)
}()
Copy the code
Based on the request
/// /// -parameters: /// -method: // -shouldCache: Equestwith public func baseRequestWith(URL: String, method: request for request failure) HTTPMethod, shouldCache: Bool, params: [String : Any]? , success: @escaping BWNetworkSuccess, fail: @escaping BWNetworkFail) { var urlPath: String = url / / stitching domain urlPath = CWAppConfig Shared. RouterUrl + urlPathif networkStatus.rawValue == BWNetworkStatus.unkonw.rawValue || networkStatus.rawValue == BWNetworkStatus.notReachable.rawValue {
if shouldCache == true{// Fetch the data from the cachelet cacheData = self.cacheDataFrom(urlPath: urlPath)
ifcacheData ! Self. fetchData(cacheData as AnyObject, success)}if self.networkStatus == .notReachable || self.networkStatus == .unkonw {
return; }}} // Clear Spacesif urlPath.contains("") {
urlPath = urlPath.replacingOccurrences(of: "", with: "")
}
var tempParams = params
ifTempParams == nil {tempParams = [String: Any]()} ["token"] = USERINFO.token ?? ""
self.currentRequestUrl = urlPath
self.currentRequestMethod = method
self.currentParams = tempParams
self.shouldCache = shouldCache
BWLog(\(String(describing: sell.currentParams))" \(sell.currentrequestURL) \(String(describing: sell.currentParams))") / / get the data from the server self. Our sessionManager. Request (self currentRequestUrl, method: self. CurrentRequestMethod, the parameters: self.currentParams, encoding: URLEncoding.default, headers: nil).responseJSON { (responseData)in
switch responseData.result {
case .success:
if letvalue = responseData.result.value as? [String: Any] {// Is a dictionary where you can customize some processing (check whether the interface returns correct data whether the interface reported an error type whether you need to log in again...) self.fetchData(value as AnyObject, success)let resultDic: [String: AnyObject] = value as [String: AnyObject]
let code: String = resultDic["code"] as! String
let isSuccess = code == "40000"
if code == "40004"{/ / delete user information to log on to the USERINFO. RemoveLocalUserInfo () CWLoginHandle. ShowLoginVC ()} / / determine whether need to cache dataif shouldCache == true && isSuccess == true{/ / cache the current interface data returned by the self. The cacheResponseDataWith (responseData: value as AnyObject, urlPath: urlPath)}}case .failure(let error):
fail(error as AnyObject)
debugPrint("Interface request failed --\(error)"FetchData (_ responseData: AnyObject, _ success: BWNetworkSuccess) {let resultDic: [String: AnyObject] = responseData as! [String: AnyObject]
let code: String = resultDic["code"] as! String
let hint: String = resultDic["hint"] as! String
let list: AnyObject = resultDic["list"] as AnyObject
let isSuccess: Bool = code == "40000"
success(isSuccess,code,hint,list,responseData as AnyObject)
}
Copy the code
GET & POST
//MARK: GET request -- no interface cache /// GET request /// /// -parameters: /// -url: request link /// -params: request parameter /// -success: Public func requestGetWith(url: String, params: [String: Any]? , success: @escaping BWNetworkSuccess, fail: @escaping BWNetworkFail) { self.requestGetWith(url: url, params: params, shouldCache:false, success: success, fail: fail)} //MARK: POST request -- no interface cache /// POST request /// /// -parameters: /// -url: request link /// -params: Public func requestPostWith(url: String, params: [String: Any]? , success: @escaping BWNetworkSuccess, fail: @escaping BWNetworkFail) { self.requestPostWith(url: url, params: params, shouldCache:false, success: success, fail: fail)} //MARK: GET request -- carry whether to cache parameter /// GET request -- carry whether to cache parameter /// /// - Parameters: /// - url: Request route /// -params: request parameters /// -shouldCache: Whether to cache data /// -success: successful callback /// -fail: Public func requestGetWith(url: String, params: [String: Any]? , shouldCache: Bool, success: @escaping BWNetworkSuccess, fail: @escaping BWNetworkFail) { self.baseRequestWith(url: url, method: .get, shouldCache: shouldCache, params: params, success: success, fail: fail) } //MARK: /// /// - Parameters: /// - url: request route /// - params: request parameter // - shouldCache: -fail: failed callback public func requestPostWith(url: String, params: [String: Any]? , shouldCache: Bool, success: @escaping BWNetworkSuccess, fail: @escaping BWNetworkFail) { self.baseRequestWith(url: url, method: .post, shouldCache: shouldCache, params: params, success: success, fail: fail) }Copy the code
Concurrent request multiple interfaces – The return interface has the urlPath passed in as the key in the dictionary
// asynchronous multi-interface request -- the data returned by the dictionary array form of [urlPath: responseData] returns /// /// -parameters in the order passed to mutableUrls: /// -mutableurls: /// -params: BwRequestKey =. Posto must be passed if it is a POST request, otherwise it will be handled as a GET request. Public func asyncMutablRequestWith(mutableUrls: [String], shouldCache: Bool, params:[Dictionary<String, Any>]? , completionHandle: @escaping ([String: Any]) -> Void) {ifparams ! = nil && params? .count ?? 0 > 0 {// Throw exception dictionary array (params) and request route array (mutableUrls) must have the same numberifparams? .count ! = mutableUrls.count { assert(false."The number of parameter dictionary arrays (Params) and request Route arrays (mutableUrls) must be the same."Var resultDictionary: Dictionary = [String: AnyObject].init() // Create a scheduling groupletDispatchGroup = dispatchgroup.init () // Create a concurrent queuelet concurrentQueue = DispatchQueue.init(label: "com.mutableNetwork.xiongbenwan", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
for (index, url) in mutableUrls.enumerated() {
var urlPath = url
if urlPath.contains("") {/ / remove the Spaces urlPath = urlPath urlPath replacingOccurrences (of:"", with: "")}ifUrlpath. count <= 0 {// Throw an exception the url passed cannot be an empty string assert(false."Urls with subscript \(index) cannot be empty strings")
}
var paramDic: Dictionary<String, Any>?
var httpMethod: HTTPMethod = .get
ifparams ! = nil && params? .count ?? 0 > 0 { paramDic = params? [index]ifparamDic ! = nil {// Fetch the dictionary for the request mode value if there is no default GET requestletrequestMethod: HTTPMethod? = paramDic! [BWRequestMethodKey] as? HTTPMethodif requestMethod == HTTPMethod.post {
httpMethod = .post
}
}
}
dispatchGroup.enter()
concurrentQueue.async {
self.baseRequestWith(url: urlPath, method: httpMethod, shouldCache: shouldCache, params: paramDic, success: { (isSuccess, code, hint, list, responseData) inResultDictionary [urlPath] = responseData dispatchgroup.leave ()}, fail: {(error)inResultDictionary [urlPath] = error dispatchgroup. leave()})}} DispatchQueue.main) { completionHandle(resultDictionary) } }Copy the code
Data cache correlation
/// /// -parameter urlPath: request route /// - Returns: Func cacheDataFrom(urlPath: String) -> Any? {// Base64 encodes the request routeletBase64Path = urlpath.md5string ()() // concatenating cachePath var directorPath: String = cachePath directorpath.append (base64Path)let data: Data? = FileManager.default.contents(atPath: directorPath)
let jsonData: Any?
ifdata ! = nil {print("Get data from cache :\(directorPath)")
do{ jsonData = try JSONSerialization.jsonObject(with: data! , options: .mutableContainers)return jsonData
} catch {
return data
}
}
return// -responseData: /// -urlPath: request route /// -params: Public func cacheResponseDataWith(responseData: AnyObject, urlPath: String) {var directorPath: String = cachePath // Creating a directory createRootCachePath(Path: directorPath) // Base64 encoding of the requested routeletBase64Path = urLPath.md5String () // Concatenate path directorPath.appEnd (base64Path) // Convert returned Data to Data var Data: Data?do{try data = JSONSerialization. Data (withJSONObject: responseData, options:.prettyprinted)} catch {} // Stores data to the specified pathifdata ! = nil {let cacheSuccess = FileManager.default.createFile(atPath: directorPath, contents: data, attributes: nil)
if cacheSuccess == true {
debugPrint("Current interface cache successful :\(directorPath)")}else {
debugPrint("Current interface cache failed :\(directorPath)"Func createRootCachePath(path: String) {createRootCachePath(String) {if! FileManager.default.fileExists(atPath: path, isDirectory: nil) {do {
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
} catch let error {
debugPrint("create cache dir error:" + error.localizedDescription + "\n")
return}}}}Copy the code
Network status monitoring
Extension BWNetworkingService {/// extension BWNetworkingService public funcmonitorNetworkingStatus() {
letreachability = NetworkReachabilityManager() reachability? .startListening() reachability? .listener = { [weak self] statusin
guard let weakSelf = self else { return }
ifreachability? .isReachable ??false {
switch status {
case .notReachable:
weakSelf.networkStatus = BWNetworkStatus.notReachable
case .unknown:
weakSelf.networkStatus = BWNetworkStatus.unkonw
case .reachable(.wwan):
weakSelf.networkStatus = BWNetworkStatus.wwan
case .reachable(.ethernetOrWiFi):
weakSelf.networkStatus = BWNetworkStatus.wifi
}
} else {
weakSelf.networkStatus = BWNetworkStatus.notReachable
}
}
}
}
Copy the code
Knock it off!!