以前開始學習iOS的時候網(wǎng)絡(luò)請求都是直接用AFN俩莽,每一次請求都特別繁瑣芋肠,最近完善了一下自己寫的請求封裝蝇更,分享一下岭洲。
以下代碼為Swift版本宛逗,如果需要Object-c的可以去我的github(https://github.com/JakeZhucl/CLBaseObject-C)下載
下面是我心里想的封裝需求:
1.添加公共參數(shù)
2.緩存請求的結(jié)果
3.要可以處理tableview, scrollview,collectionview的停止刷新
4.可以加密
5.打印對應(yīng)的請求、參數(shù)钦椭、加密參數(shù)和結(jié)果
開始吧
1.既然需要處理公共參數(shù)拧额,那就寫一個處理參數(shù)的方法
private class func addPostParameters( parameters : Dictionary<String, Any>?) -> Dictionary<String, Any>{
var newParameters = Dictionary<String,Any>()
/*這里的內(nèi)容都是公共參數(shù),看需求添加
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")
//如果沒有參數(shù)傳入就直接返回公共參數(shù)彪腔,如果有參數(shù)傳入就將參數(shù)字典的東西通過遍歷加到公共參數(shù)返回作為最后的請求參數(shù)
if parameters == nil {
return newParameters
}else{
for (key,value) in parameters!{
newParameters[key] = value
}
return newParameters
}
}
2.緩存我采用的yycache這個第三方庫(主要是這個用習慣了
let clCache = YYCache(name: "product_name")
//講請求的參數(shù)字典的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就是請求路徑和請求參數(shù)要放進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 {
//請求結(jié)束的時候就可以將請求結(jié)果當作value,剛剛的url當作key存到本地了
clCache?.setObject(response.data! as NSData, forKey: cacheURL)
}
}
}
}
3.添加自動停止刷新的方法德挣,這個真的非常有用恭垦,添加后,在寫tableview格嗅、scorllview番挺、collection就完全不用考慮是否會出現(xiàn)忘記寫停止刷新的方法了
//我這里是將請求已經(jīng)全部轉(zhuǎn)換成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.加密 我公司根據(jù)項目采用des還是aes(不知道為什么屯掖,可能是哪個代碼好復(fù)制用哪個吧
//這個isDes是一個屬性 用來控制萬一項目不采用加密的方式就不用去除代碼了(如果你的需求是項目某一個請求不需要加密玄柏,那你就再通過函數(shù)的參數(shù)來控制
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 返回結(jié)果為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: "網(wǎng)絡(luò)請求失敗贴铜,錯誤代碼(-1001)", code: -1001, userInfo: nil)
fail(error)
}
}else{
SVProgressHUD.showError(withStatus: response.error?.localizedDescription)
SVProgressHUD.dismiss(withDelay: 1)
fail(response.error!)
}
}
}
/// 返回結(jié)果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: "網(wǎng)絡(luò)請求失敗粪摘,錯誤代碼(-1002)", code: -1001, userInfo: nil)
SVProgressHUD.showError(withStatus: "網(wǎng)絡(luò)請求失敗,錯誤代碼(-1002)")
SVProgressHUD.dismiss(withDelay: 1)
fail(error)
}
}else{
SVProgressHUD.showError(withStatus: response.error?.localizedDescription)
SVProgressHUD.dismiss(withDelay: 1)
fail(response.error!)
}
}
}
/// 返回結(jié)果為JSON和Model.
///
/// - Parameters:
/// - url: 路徑
/// - parameters: 參數(shù)
/// - 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: "網(wǎng)絡(luò)請求失敗绍坝,錯誤代碼(-1001)", code: -1001, userInfo: nil)
SVProgressHUD.showError(withStatus: "網(wǎng)絡(luò)請求失敗徘意,錯誤代碼(-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)
}
/// 返回結(jié)果為JSON.
///
/// - Parameters:
/// - url: 路徑
/// - parameters: 參數(shù)
/// - 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)
}
/// 返回結(jié)果為Model.
///
/// - Parameters:
/// - url: 路徑
/// - parameters: 參數(shù)
/// - 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)
}
/// 請求結(jié)束停止scorllview的刷新返回參數(shù)為JSON和Model.
///
/// - Parameters:
/// - url: 路徑
/// - parameters: 參數(shù)
/// - 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()
}
}
}
}