Alamofire是原AFNetworking团队针对Swift语言封装的网络请求库,相较于AF基本不存在内存泄漏的问题。最新版是Alamofire5最低支持系统为iOS10,具体可参考文章:Alamofire 5 的使用 - 基本用法。针对AF框架存在的内存泄漏解决方案,博客园有很多文章,尤其是文件、图片上传导致的内存泄漏。具体可参考:[AFHTTPSessionManager manager]内存泄漏解决。
下面就将Alamofire 在PUT、POST请求下body 传值以及图片、文件上传的调用简单二次封装列出如下,供参考和学习使用:
/**!
* post 接口请求
* @para strUrl String 请求地址
* @para body Data? 请求参数
* @para successBack 成功回调
* @para failureBack 失败回调
*/
func postRequestWithBodyFor(strUrl:String,
withBody body:Data?,
AndSuccessBack successBack:@escaping SuccessBlock,
AndFailureBack failureBack:@escaping FailureBlock,
WithisLoading isLoading:Bool = true) {
if body != nil {
print("请求地址:\(strUrl),参数:\(NSString.init(data: body!, encoding: String.Encoding.utf8.rawValue) ?? "暂无参数")")
}
else{
print("请求地址:\(strUrl),暂无参数")
}
if isLoading == true {
SVProgressHUD.showLoading()
}
var request = URLRequest.init(url: URL.init(string: strUrl)!)
request.httpBody = body
request.httpMethod = "POST"
request.timeoutInterval = K_APP_REQUEST_TIME_OUT
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json;charset=UTF-8", forHTTPHeaderField: "Content-Type")
Alamofire.request(request)
.validate()
.validate(contentType: K_APP_ACCEPTABLE_CONTENTTYPES)
.responseJSON { response in
if isLoading == true {
SVProgressHUD.dismissLoading()
}
var msg:String? = response.error?.localizedDescription ?? "请求数据不存在"
self.errorHandle(Error: response.error as NSError?,
statusCode: response.response?.statusCode,
andErrormsg: &msg)
print("请求结果:\(response)")
if response.error != nil {
failureBack(msg)
}
else{
if let jsonObj:[String:Any] = response.value as? [String:Any] {
var code:Int? = jsonObj[K_API_RESULT_CODE] as? Int
if code == nil, let strTemp = jsonObj[K_API_RESULT_CODE] as? String {
code = NSNumber.init(string:strTemp)?.intValue
}
//请求成功
if K_API_IS_OK(rs: code) {
successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? nil : jsonObj[K_API_RESULT_DATA])
}
//京东AI拍照识别
else if code == 10000 {
successBack(jsonObj["result"] is NSNull ? nil : jsonObj["result"])
}
else if code == 200 {
successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? nil : jsonObj[K_API_RESULT_DATA])
}
else{
failureBack("\(jsonObj[K_API_RESULT_MESSAGE] ?? "请求失败")")
}
}
else{
failureBack(msg)
}
}
}
}
/// OAuth Password 网络请求
/// https://github.com/AFNetworking/AFOAuth2Manager
/// - Parameters:
/// - un: 用户名
/// - pwd: 密码
/// - successBack: 成功回调
/// - failureBack: 失败回调
/// - isLoading: 是否显示加载
func oAuthRequestPasswordFor(Username un:String,
andPwd pwd:String,
andSuccessBack successBack:@escaping SuccessBlock,
andFailureBack failureBack:@escaping FailureBlock,
withisLoading isLoading:Bool = true){
print("请求参数:\(un),\(pwd)")
let strUrl = String.init(format:"%@oauth/token",K_APP_OAUTH_HOST)
if isLoading == true {
SVProgressHUD.showLoading()
}
let dicParam = [
"username": un,
"password": pwd,
"grant_type":"password",
"client_id":K_APP_IS_PRODUCT ? K_APP_CLIENT_ID_PRO : K_APP_CLIENT_ID_DEV,
"client_secret":K_APP_IS_PRODUCT ? K_APP_CLIENT_SECRET_PRO : K_APP_CLIENT_SECRET_DEV
]
Alamofire.request(strUrl,
method: .post,
parameters: dicParam)
.validate()
.responseJSON { response in
if isLoading == true {
SVProgressHUD.dismissLoading()
}
var msg:String? = response.error?.localizedDescription ?? "请求数据不存在"
self.errorHandle(Error: response.error as NSError?,
statusCode: response.response?.statusCode,
andErrormsg: &msg)
print("请求结果:\(response)")
if response.error != nil {
failureBack(msg)
}
else{
if let jsonObj:[String:Any] = response.value as? [String:Any] {
let access_token:String? = jsonObj[UserModel.k_user_tooken] as? String
if access_token == nil || access_token == "" {
failureBack("用户名或密码错误")
}
else{
//请求成功
successBack(access_token)
}
}
else{
failureBack("请求token不存在")
}
}
}
}
/**!
* 文件或图片上传
* @para strUrl String 上传地址
* @para uploadformDataBack 上传参数设置
* @para successBack 成功回调
* @para failureBack 失败回调
*/
func postImageUploadToServer(strUrl:String,
uploadformDataBack:@escaping(_ fData:MultipartFormData)->(Void),
AndSuccessBack successBack:@escaping SuccessBlock,
AndFailureBack failureBack:@escaping FailureBlock,
WithisLoading isLoading:Bool = true){
print("上传地址:\(strUrl)")
if isLoading == true {
SVProgressHUD.showLoading()
}
Alamofire.upload(multipartFormData: { (_multipartFormData:MultipartFormData) in
//指定参数
uploadformDataBack(_multipartFormData)
},
to: strUrl) { encodingResult in
if isLoading == true {
SVProgressHUD.dismissLoading()
}
switch(encodingResult){
case .success(let upload,_,_):
upload.responseJSON { response in
print("上传结果:\(response)")
let result = response.result
if result.isSuccess {
if let jsonObj:[String:Any] = response.value as? [String:Any] {
//请求成功
if K_API_IS_OK(rs: jsonObj[K_API_RESULT_CODE]) || jsonObj[K_API_RESULT_CODE] as? Int == 200 {
successBack(jsonObj[K_API_RESULT_DATA] is NSNull ? Any.self : jsonObj[K_API_RESULT_DATA])
}
else{
failureBack("\(jsonObj[K_API_RESULT_MESSAGE] ?? "请求失败")")
}
}
else{
failureBack("请求数据不存在")
}
}
else{
failureBack("请求数据不存在")
}
}
.validate()
break
case .failure(let error):
failureBack("\(error.localizedDescription)")
break
}
}
}
备注:
经过实际使用测试在Alamofire4(V4.9.1.1)中,由于请求的参数为Option可选类型,会导致部分请求失败,此情况下需要将参数使用"!"或"guard"进行强制拆包。
Alamofire 使用CocoaPods导入到项目等操作知识点,请自行查找资料。
如上案例部分私有方法,参考如下:
import Alamofire.Swift
import SVProgressHUD
typealias SuccessBlock = (_ responseData:Any?) -> (Void)
typealias FailureBlock = (_ responseString:String?) -> (Void)
//MARK: - errorHandle
private func errorHandle(Error e:NSError?,
statusCode:Int?,
andErrormsg ems:inout String?) {
let code:Int? = e?.code
print("error code:\(code ?? 0)")
//https://www.jb51.net/article/105163.htm
switch statusCode {
case .some(302):
ems = "请求被重定向"
case .some(400):
ems = "发送的请求有语法错误"
case .some(401):
ems = "访问没有授权"
case .some(403):
ems = "没有权限访问"
case .some(404):
ems = "请求地址不存在"
case .some(405):
ems = "请求方式不存在"
case .some(408),.some(504):
ems = "请求超时,请检查网络或重试"
case .some(500):
ems = "服务器内部异常,无法完成请求处理"
case .some(507):
ems = "服务器无法存储完成请求所必须的内容"
case .some(509):
ems = "服务器达到带宽限制"
case .some(510):
ems = "获取资源所需要的策略并没有没满足"
default:
break
}
switch code {
case .some(-1001):
ems = "请求超时"
//token 过期
case .some(-1011),.some(3):
if statusCode == 401 {
//...
}
case .some(-32700):
ems = "类型转换错误"
case .some(-32600):
ems = "无效的请求"
case .some(-32601):
ems = "没有找到方法"
case .some(-32602):
ems = "无效的参数"
case .some(-32603):
ems = "网络异常,请检查网络"
default:
break
}
}
/** 网络请求状态判断(0 成功) */
func K_API_IS_OK(rs:Any?) -> Bool {
guard let _rt:Int = rs as? Int else {
return false
}
return _rt == 0
}