swift同樣可以實現(xiàn)OC中AFNetworking+MJExtension的效果,實現(xiàn)方法是Alamofire+SwiftyJSON+HandyJSON
Alamofire:網(wǎng)絡(luò)請求
SwiftyJSON:數(shù)據(jù)解析
HandyJSON:映射為model
一、獲取SessionManager子類的單例
節(jié)約系統(tǒng)開支不用每次網(wǎng)絡(luò)請求都生成一個SessionManager子類對象
//
// TMNetManager.swift
// ivygateCRM
//
// Created by 紀(jì)志剛 on 2018/7/27.
// Copyright ? 2018年 紀(jì)志剛. All rights reserved.
//
import UIKit
import Alamofire
/// 網(wǎng)絡(luò)配置單例類
class TMNetManager: SessionManager {
static var theManager:TMNetManager?
class func shareManager(timeOutFlo:TimeInterval = 60) -> TMNetManager {
let config = Config.shareConfig()
config.timeoutIntervalForRequest = timeOutFlo
if theManager == nil{
theManager = TMNetManager.init(configuration: config)
}
return theManager!
}
}
/// 網(wǎng)絡(luò)配置單例類
class Config: URLSessionConfiguration {
static var theConfig:URLSessionConfiguration?
class func shareConfig() -> URLSessionConfiguration {
if theConfig == nil {
theConfig = URLSessionConfiguration.default
}
return theConfig!
}
}
二、網(wǎng)絡(luò)請求
//
// TMNetworkingTool.swift
// ivygateSwift
//
// Created by 紀(jì)志剛 on 2018/4/24.
// Copyright ? 2018年 紀(jì)志剛. All rights reserved.
//
import UIKit
import HandyJSON
import Alamofire
import SwiftyJSON
class TMNetworkingTool: NSObject {
static private var isFirst:Bool = true //是否是第一次點擊“確定”按鈕
private static func setHttpHeader() -> HTTPHeaders {
let Dic = Bundle.main.infoDictionary
// let buildStr = Dic?["CFBundleVersion"] ?? "" //內(nèi)部管理版本號
let versionStr = Dic?["CFBundleShortVersionString"] ?? "" //版本號
//= ["os":"ios","appname":"crm","version":versionStr as! String,"Content-Type":"application/json;charset=UTF-8"]
var header:HTTPHeaders = HTTPHeaders.init()
header["os"] = "iOS"
header["Content-Type"] = "application/json;charset=UTF-8"
return header
}
/// 網(wǎng)絡(luò)請求 get/post
///
/// - Parameters:
/// - url: 鏈接
/// - method: get/post
/// - parameters: 參數(shù)列表
/// - showLoading: 是否顯示loading true顯示 false不顯示
/// - succ: 請求成功 jsonStr:獲取結(jié)果的json字符串。headerJsonStr:獲取的header的json字符串 將返回的所有數(shù)據(jù)都返回過去,方便以后取responseHeader中的內(nèi)容
/// - fail: 請求失敗 errStr:經(jīng)過處理的錯誤信息 err:未經(jīng)整理的錯誤信息
static func requestFun(url:String, method:HTTPMethod, parameters:Parameters?,showLoading:Bool = true, succ: @escaping (_ jsonStr: String, _ responseJson: DataResponse<String>) -> Void, fail: @escaping (_ errStr: String,_ err:Error)->()) {
if showLoading { //顯示loading
TMNetworkingTool.referenceCountChangeFun(isAdd: true)
}
var urlStr:String = url
let header = self.setHttpHeader()
let encoding:ParameterEncoding = JSONEncoding.default
if method == kHTTPMethodGet {
let theStr:NSString = NSString.init(string: urlStr)
urlStr = theStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
}
TMNetManager.shareManager().request(urlStr, method: method, parameters: parameters, encoding: encoding, headers: header).responseString { (response) in
if showLoading { //顯示loading
TMNetworkingTool.referenceCountChangeFun(isAdd: false)
}
if response.result.isSuccess { //網(wǎng)絡(luò)請求成功
print("header=\(header) \rurlStr=\(urlStr) \rparaDic=\(parameters ?? [:]) \rresponse=\(JSON.init(parseJSON: response.result.value ?? ""))")
if let value = response.result.value {
let json = JSON.init(parseJSON: value)
if json["code"].int == 0 {//請求成功
succ(value,response)
}
else{//請求失敗,獲取err
fail(json["message"].string ?? kNetFailMessage, response.error ?? NSError.init())
}
}else{ //沒有獲取到數(shù)據(jù)
fail(kNetFailMessage, NSError.init())
}
}else {//網(wǎng)絡(luò)請求失敗
fail(kNetFailMessage, NSError.init())
}
}
}
/// 文件上傳
///
/// - Parameters:
/// - url: 鏈接
/// - parameters: 參數(shù)
/// - name: 文件對應(yīng)key
/// - fileName: fileName
/// - mimeType: mimeType
/// - imgData: 文件流
/// - showLoading: 是否顯示loading true顯示 false不顯示
/// - succ: <#succ description#>
/// - fail: <#fail description#>
static func uploadFun(url:String,method:HTTPMethod, parameters:Dictionary<String, String>?, name:String, fileName:String ,mimeType:String ,imgData:Data ,showLoading:Bool = true, succ: @escaping (_ jsonStr: String, _ responseJson: DataResponse<String>) -> Void, fail: @escaping (_ errStr: String,_ err:Error)->()) {
let urlStr = url
let header = self.setHttpHeader()//請求頭
TMNetManager.shareManager(timeOutFlo: 60).upload(multipartFormData: { multipartFormData in
//采用post表單上傳
// 參數(shù)解釋:
//withName:和后臺服務(wù)器的name要一致 ;fileName:可以充分利用寫成用戶的id,但是格式要寫對; mimeType:規(guī)定的,要上傳其他格式可以自行百度查一下
multipartFormData.append(imgData, withName: name, fileName: fileName, mimeType: mimeType)
//如果需要上傳多個文件,就多添加幾個
//multipartFormData.append(imageData, withName: "file", fileName: "123456.jpg", mimeType: "image/jpeg")
//......
if parameters?.keys != nil && (parameters?.keys.count)! > 0{
for str in (parameters?.keys)! {
let value = parameters![str]
multipartFormData.append((value?.data(using: String.Encoding.utf8))!, withName: str)
}
}
}, usingThreshold: SessionManager.multipartFormDataEncodingMemoryThreshold, to: urlStr, method: method, headers: header) { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
//連接服務(wù)器成功后,對json的處理
upload.responseString(completionHandler: { response in
if response.result.isSuccess { //網(wǎng)絡(luò)請求成功
print("header=\(header) \rurlStr=\(urlStr) \rparaDic=\(parameters ?? [:]) \rresponse=\(JSON.init(parseJSON: response.result.value ?? ""))")
if let value = response.result.value {
let json = JSON.init(parseJSON: value)
if json["code"].int == 1 || json["code"].int == 0 {//請求成功
succ(value,response)
}
else{//請求失敗,獲取err
fail(json["message"].string ?? kNetFailMessage, response.error ?? NSError.init())
}
}else{ //沒有獲取到數(shù)據(jù)
fail(kNetFailMessage, NSError.init())
}
}else {//網(wǎng)絡(luò)請求失敗
fail(kNetFailMessage, NSError.init())
}
})
//獲取上傳進度
upload.uploadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("圖片上傳進度: \(progress.fractionCompleted)")
}
break
case .failure( _):
fail(kNetFailMessage, NSError.init())
break
}
}
}
/// loading 管理
///
/// - Parameter isAdd: 是否顯示loading true引用計數(shù)加一 false引用計數(shù)減一
private static func referenceCountChangeFun(isAdd:Bool) {
if isAdd {
KNetReferenceCount += 1
DispatchQueue.main.async {
TMLoading.shareInstance.show(title: "正在加載")
}
}else{
KNetReferenceCount -= 1
if KNetReferenceCount <= 0 {
KNetReferenceCount = 0
DispatchQueue.main.async {
TMLoading.shareInstance.dismissLoading()
}
}
}
}
/// 網(wǎng)絡(luò)請求 get/post
///
/// - Parameters:
/// - url: 鏈接
/// - method: get/post
/// - parameters: 參數(shù)列表
/// - showLoading: 是否顯示loading true顯示 false不顯示
/// - succ: 請求成功 responseModel:獲取結(jié)果的模型。responseJson獲取的所有信息,方便單獨獲取另外字段
/// - fail: 請求失敗 errStr:經(jīng)過處理的錯誤信息 err:未經(jīng)整理的錯誤信息
public static func request<T:HandyJSON>(t:T.Type,url:String, method:HTTPMethod, parameters:Parameters?,showLoading:Bool = true, succ: @escaping (_ responseModel: T, _ responseJson: DataResponse<String>) -> (), fail: @escaping (_ errStr: String,_ err:Error)->()){
if showLoading { //顯示loading
TMNetworkingTool.referenceCountChangeFun(isAdd: true)
}
var urlStr:String = url
var header = self.setHttpHeader()
var encoding:ParameterEncoding = JSONEncoding.default
if method == kHTTPMethodGet {
let theStr:NSString = NSString.init(string: urlStr)
urlStr = theStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
}
TMNetManager.shareManager().request(urlStr, method: method, parameters: parameters, encoding: encoding, headers: header).responseString { (response) in
if showLoading { //顯示loading
TMNetworkingTool.referenceCountChangeFun(isAdd: false)
}
if response.result.isSuccess { //網(wǎng)絡(luò)請求成功
print("header=\(header) \rurlStr=\(urlStr) \rparaDic=\(parameters ?? [:]) \rresponse=\(JSON.init(parseJSON: response.result.value ?? ""))")
if let value = response.result.value {
let json = JSON.init(parseJSON: value)
if json["code"].int == 1 {//請求成功
print("json[kNet_data_Key]原始值 == \(json["data"])")
print("json[kNet_data_Key].dictionaryValue == \(json["data"].dictionaryValue.keys.count)")
print("json[kNet_data_Key].arrayValue == \(json["data"].arrayValue.count)")
print("json[kNet_data_Key].stringValue == \(json["data"].stringValue.count)")
if json["data"].dictionaryValue.keys.count > 0{ //data中是數(shù)據(jù)是非空字典
let responseModel:T = JSONDeserializer<T>.deserializeFrom(json: value, designatedPath: "data") ?? T.init()
succ(responseModel,response)
}
else{//是不確定類型,返回response原始值以備后續(xù)操作(空字典、空數(shù)組、空字符串等等)
succ(T.init(),response)
}
}
else{//請求失敗,獲取err
fail(json["message"].string ?? kNetFailMessage, response.error ?? NSError.init())
}
}else{ //沒有獲取到數(shù)據(jù)
fail(kNetFailMessage, NSError.init())
}
}else {//網(wǎng)絡(luò)請求失敗
fail(kNetFailMessage, NSError.init())
}
}
}
}
三、使用
新建model類
//
// TMMineModel.swift
// ivygateSwift
//
// Created by 紀(jì)志剛 on 2018/4/24.
// Copyright ? 2018年 紀(jì)志剛. All rights reserved.
//
import UIKit
import HandyJSON
class TMMineModel: HandyJSON {
var code:String = ""
var name:String = ""
var domain:String = ""
var captcha:Bool = false
//HandyJSON要求必須實現(xiàn)這個方法
required init() {
}
/// 獲取個人信息
///
/// - Parameters:
/// - succ: <#succ description#>
/// - fail: <#fail description#>
static func requestFun(succ: @escaping(_ arr:Array<TMMineModel>) -> (), fail: @escaping (_ errStr: String) -> ()) {
TMNetworkingTool.requestFun(url: "你自己的網(wǎng)絡(luò)請求", method: kHTTPMethodGet, parameters: nil, showLoading: false, succ: { (responseData, response) in
succ([TMMineModel].deserialize(from: responseData, designatedPath: "data") as? Array<TMMineModel> ?? Array.init())
}) { (errStr, err) in
fail(errStr)
}
}
}
使用方法
TMMineModel.requestFun(succ: { (model) in
print("網(wǎng)絡(luò)請求成功了")
}) { (errStr) in
print("失敗了")
}

image
可以看到網(wǎng)絡(luò)請求成功之后返回了一個數(shù)組,數(shù)組內(nèi)是自定義數(shù)據(jù)類型
HandyJSON用于數(shù)據(jù)映射時注意
- model類繼承自HandyJSON并實現(xiàn)init方法
//HandyJSON要求必須實現(xiàn)這個方法
required init(){}
2.重命名屬性時實現(xiàn)方法
func mapping(mapper: HelpingMapper) {
mapper <<<
self.ID <-- "id"
mapper <<<
self.Description <-- "description"
}
3.映射為model類和映射為model數(shù)組的用法分別為
TMMineSaleStatusModel.deserialize(from: jsonStr, designatedPath: kNet_data_Key) ?? TMMineSaleStatusModel.init()
[TMMineSaleStatusModel].deserialize(from: jsonStr, designatedPath: kNet_data_Key) as? Array<TMMineSaleStatusModel> ?? Array.init()