以前开始学习iOS的时候网络请求都是直接用AFN,每一次请求都特别繁琐,最近完善了一下自己写的请求封装,分享一下。
以下代码为Swift版本,如果需要Object-c的可以去我的github(https://github.com/JakeZhucl/CLBaseObject-C)下载
下面是我心里想的封装需求:
1.添加公共参数
2.缓存请求的结果
3.要可以处理tableview, scrollview,collectionview的停止刷新
4.可以加密
5.打印对应的请求、参数、加密参数和结果
开始吧
1.既然需要处理公共参数,那就写一个处理参数的方法
private class func addPostParameters( parameters : Dictionary<String, Any>?) -> Dictionary<String, Any>{
var newParameters = Dictionary<String,Any>()
/*这里的内容都是公共参数,看需求添加
newParameters["vid"] = Account.account().vid
newParameters["user_id"] = Account.account().user_id
newParameters["app_flag"] = APP_FLAG
newParameters["device"] = "iOS"
*/
//版本号
newParameters["version"] = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
//bundleId
newParameters["bundleid"] = Bundle.main.object(forInfoDictionaryKey: "CFBundleIdentifier")
//如果没有参数传入就直接返回公共参数,如果有参数传入就将参数字典的东西通过遍历加到公共参数返回作为最后的请求参数
if parameters == nil {
return newParameters
}else{
for (key,value) in parameters!{
newParameters[key] = value
}
return newParameters
}
}
2.缓存我采用的yycache这个第三方库(主要是这个用习惯了
let clCache = YYCache(name: "product_name")
//讲请求的参数字典的key变成有序的,为了下一步存储的时候变成string不会每次都不一样
let parametersKeys = addParameters.keys.sorted { (num1 , num2) -> Bool in
return num1 < num2
}
var cacheString = ""
for key in parametersKeys {
if key != "lat" && key != "lng" {
cacheString += "\(key)\(String(describing:addParameters[key]))"
}
}
//这个cacheurl就是请求路径和请求参数要放进cache的key
let cacheURL = "\(url)\(cacheString)"
Alamofire.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: nil).response { (response) in
SVProgressHUD.setDefaultMaskType(.none)
if (response.error == nil ) {
if response.data != nil {
if isCache {
//请求结束的时候就可以将请求结果当作value,刚刚的url当作key存到本地了
clCache?.setObject(response.data! as NSData, forKey: cacheURL)
}
}
}
}
3.添加自动停止刷新的方法,这个真的非常有用,添加后,在写tableview、scorllview、collection就完全不用考虑是否会出现忘记写停止刷新的方法了
//我这里是将请求已经全部转换成model了
private class func endRefresh(model : CLNetWorkModel,
scrollview : UIScrollView ,
isCache : Bool){
if !isCache {
//后端返回isnull来控制是否最后一页,所以这边由isnull控制是否endRefreshing
if model.isnull == "0" {
if scrollview.mj_footer != nil {
scrollview.mj_footer.endRefreshing()
}
}else{
if scrollview.mj_footer != nil {
scrollview.mj_footer.endRefreshingWithNoMoreData()
}
}
if scrollview.mj_header != nil {
scrollview.mj_header.endRefreshing()
}
}
}
4.加密 我公司根据项目采用des还是aes(不知道为什么,可能是哪个代码好复制用哪个吧
//这个isDes是一个属性 用来控制万一项目不采用加密的方式就不用去除代码了(如果你的需求是项目某一个请求不需要加密,那你就再通过函数的参数来控制
if isDes {
parameters["data"] = CLDes.encryptUse(addParameters.CLDictionaryToJsonString())
print(parameters.CLDictionaryToJsonString())
}else{
parameters = addParameters
}
好啦。我把全部代码放上去
//
// CLNetworkingSwift.swift
// Created by zcl on 2018/2/6.
//
import UIKit
import Alamofire
import SwiftyJSON
import HandyJSON
import SVProgressHUD
import MJRefresh
import YYCache
class CLNetWorkModel: HandyJSON {
var data : AnyObject?
var isnull = "0"
var ret = "-100"
var code : String?
var page = "0"
required init() {
}
}
class CLNetworkSwift {
enum CLNetWorkType {
case notReachable
case unknown
case wwan
case ethernetOrWiFi
}
static let isDes = true
func networkState(state : @escaping (_ type : CLNetWorkType) ->Void )
-> Void {
let networkManager = NetworkReachabilityManager.init(host: YM)
networkManager?.listener = { status in
switch status {
case .notReachable:
state(.notReachable)
break
case .unknown:
state(.unknown)
break
case .reachable(NetworkReachabilityManager.ConnectionType.wwan):
state(.wwan)
break
case .reachable(NetworkReachabilityManager.ConnectionType.ethernetOrWiFi):
state(.ethernetOrWiFi)
break
}
}
networkManager?.startListening()
}
/// GET 返回结果为JSON.
class func GET(url : String ,
parameters : Dictionary<String, Any>? ,
successJson success : @escaping (_ success : JSON) -> Void ,
fail : @escaping (_ fail : Error) -> Void) {
print(url)
print(self.addPostParameters(parameters: parameters).CLDictionaryToJsonString())
Alamofire.request(url, method: .get, parameters: self.addPostParameters(parameters: parameters), encoding: URLEncoding.default, headers: nil).response { (response) in
if (response.error == nil) {
do {
success(try JSON.init(data: response.data!))
}catch{
let error = NSError.init(domain: "网络请求失败,错误代码(-1001)", code: -1001, userInfo: nil)
fail(error)
}
}else{
SVProgressHUD.showError(withStatus: response.error?.localizedDescription)
SVProgressHUD.dismiss(withDelay: 1)
fail(response.error!)
}
}
}
/// 返回结果Data.
class func POST(url : String ,
parameters : Dictionary<String, Any>? ,
successData success : @escaping (_ successData : Data , _ isCache : Bool) -> Void ,
fail : @escaping (_ fail : Error) -> Void,
isCache : Bool) {
let clCache = YYCache(name: "yixingcheng")
let addParameters = self.addPostParameters(parameters: parameters)
print(url)
print(addParameters.CLDictionaryToJsonString())
var parameters = Dictionary<String,Any>()
if isDes {
parameters["data"] = CLDes.encryptUse(addParameters.CLDictionaryToJsonString())
print(parameters.CLDictionaryToJsonString())
}else{
parameters = addParameters
}
let parametersKeys = addParameters.keys.sorted { (num1 , num2) -> Bool in
return num1 < num2
}
var cacheString = ""
for key in parametersKeys {
if key != "lat" && key != "lng" {
cacheString += "\(key)\(String(describing: addParameters[key]))"
}
}
let cacheURL = "\(url)\(cacheString)"
if isCache {
if (clCache?.containsObject(forKey: cacheURL))! {
success(clCache?.object(forKey: cacheURL) as! Data,true)
}
}
Alamofire.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: nil).response { (response) in
SVProgressHUD.setDefaultMaskType(.none)
if (response.error == nil ) {
if response.data != nil {
if isCache {
print(url)
clCache?.setObject(response.data! as NSData, forKey: cacheURL)
}
success(response.data!,false)
}else{
let error = NSError.init(domain: "网络请求失败,错误代码(-1002)", code: -1001, userInfo: nil)
SVProgressHUD.showError(withStatus: "网络请求失败,错误代码(-1002)")
SVProgressHUD.dismiss(withDelay: 1)
fail(error)
}
}else{
SVProgressHUD.showError(withStatus: response.error?.localizedDescription)
SVProgressHUD.dismiss(withDelay: 1)
fail(response.error!)
}
}
}
/// 返回结果为JSON和Model.
///
/// - Parameters:
/// - url: 路径
/// - parameters: 参数
/// - successDictionary: 字典闭包
/// - successModel: 模型闭包
/// - fail: 失败闭包
class func POST(url : String ,
parameters : Dictionary<String, Any>? ,
successJsonAndModel success : @escaping (_ success : JSON , _ success : CLNetWorkModel ,_ isCahce : Bool) -> Void ,
fail : @escaping (_ fail : Error) -> Void,
isCache : Bool) {
self.POST(url: url, parameters: parameters, successData: { (successData , isCacheData) in
do {
var JsonString = try JSON.init(data: successData)
var model : CLNetWorkModel!
if isDes {
let decry = JsonString.dictionaryObject
let result = CLDes.decryptUse(decry?["data"] as? String)
// print(result ?? "")
model = CLNetWorkModel.deserialize(from: CLDes.decryptUse(decry?["data"] as? String))
JsonString = JSON.init(parseJSON: result ?? "")
}else{
model = CLNetWorkModel.deserialize(from: JsonString.dictionaryObject)
}
if model?.ret == "1001" {
SVProgressHUD.dismiss()
success(JsonString,model, isCacheData)
}else{
print("错误接口")
print(url)
print(model?.code ?? "")
SVProgressHUD.showError(withStatus: model?.code )
SVProgressHUD.dismiss(withDelay: 1)
let error = NSError.init(domain: (model?.code ?? "")!
, code: Int((model?.ret)!)!, userInfo: nil)
fail(error)
}
}catch{
let error = NSError.init(domain: "网络请求失败,错误代码(-1001)", code: -1001, userInfo: nil)
SVProgressHUD.showError(withStatus: "网络请求失败,错误代码(-1001)")
SVProgressHUD.dismiss(withDelay: 1)
fail(error)
}
}, fail: { (error) in
SVProgressHUD.showError(withStatus: error.localizedDescription)
SVProgressHUD.dismiss(withDelay: 1)
print("请求失败")
print(url)
print(parameters?.CLDictionaryToJsonString() ?? "")
print(error.localizedDescription)
fail(error)
}, isCache: isCache)
}
/// 返回结果为JSON.
///
/// - Parameters:
/// - url: 路径
/// - parameters: 参数
/// - success: 字典闭包
/// - fail: 失败闭包
class func POST(url : String ,
parameters : Dictionary<String, Any>? ,
successJson success : @escaping (_ success : JSON,_ isCahce : Bool) -> Void ,
fail : @escaping (_ fail : Error) -> Void,
isCache : Bool) {
self.POST(url: url, parameters: parameters, successJsonAndModel: { (successJSON, successModel, isCacheData) in
success(successJSON, isCacheData)
}, fail: fail, isCache: isCache)
}
/// 返回结果为Model.
///
/// - Parameters:
/// - url: 路径
/// - parameters: 参数
/// - success: 成功闭包
/// - fail: 失败闭包
class func POST(url : String,
parameters : Dictionary<String,Any>,
successModel success : @escaping (_ success : CLNetWorkModel , _ isCahce : Bool) -> Void,
fail : @escaping (_ fail : Error)-> Void,
isCache : Bool) -> Void {
self.POST(url: url, parameters: parameters, successJsonAndModel: { (successJson, successModel, isCacheData) in
success(successModel, isCacheData)
}, fail: fail,isCache : isCache)
}
/// 请求结束停止scorllview的刷新返回参数为JSON和Model.
///
/// - Parameters:
/// - url: 路径
/// - parameters: 参数
/// - success: 成功闭包
/// - fail: 失败闭包
/// - scrollView: 需要停止刷新的scrollview、tableview、collectionview
class func POST(url : String ,
parameters : Dictionary<String, Any>?,
success : @escaping (_ success : JSON , _ success : CLNetWorkModel , _ isCahce : Bool) -> Void ,
fail : @escaping (_ fail : Error) -> Void,
scrollView : UIScrollView,
isCache : Bool) {
self.POST(url: url, parameters: parameters, successJsonAndModel: { (successJSON, successModel , isCacheData) in
self.endRefresh(model: successModel, scrollview: scrollView , isCache: isCacheData)
success(successJSON,successModel, isCacheData)
}, fail: { (error) in
self.endRefresh(model: CLNetWorkModel(), scrollview: scrollView, isCache: false)
fail(error)
}, isCache: isCache)
}
}
//配置处理
extension CLNetworkSwift {
private class func addPostParameters( parameters : Dictionary<String, Any>?) -> Dictionary<String, Any>{
var newParameters = Dictionary<String,Any>()
newParameters["vid"] = Account.account().vid
newParameters["user_id"] = Account.account().user_id
newParameters["app_flag"] = APP_FLAG
newParameters["device"] = "iOS"
newParameters["version"] = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
newParameters["bundleid"] = Bundle.main.object(forInfoDictionaryKey: "CFBundleIdentifier")
newParameters["channel_id"] = UserDefaults.standard.value(forKey: "channel_id")
if parameters == nil {
return newParameters
}else{
for (key,value) in parameters!{
newParameters[key] = value
}
return newParameters
}
}
private class func endRefresh(model : CLNetWorkModel,
scrollview : UIScrollView ,
isCache : Bool){
if !isCache {
if model.isnull == "0" {
if scrollview.mj_footer != nil {
scrollview.mj_footer.endRefreshing()
}
}else{
if scrollview.mj_footer != nil {
scrollview.mj_footer.endRefreshingWithNoMoreData()
}
}
if scrollview.mj_header != nil {
scrollview.mj_header.endRefreshing()
}
}
}
}