当前位置: 首页 > 工具软件 > Swift OAuth2 > 使用案例 >

Alamofire4 PUT、POSTbody传参以及实现Oauth2认证

魏刚豪
2023-12-01

       Alamofire是原AFNetworking团队针对Swift语言封装的网络请求库,相较于AF基本不存在内存泄漏的问题。最新版是Alamofire5最低支持系统为iOS10,具体可参考文章:Alamofire 5 的使用 - 基本用法。针对AF框架存在的内存泄漏解决方案,博客园有很多文章,尤其是文件、图片上传导致的内存泄漏。具体可参考:[AFHTTPSessionManager manager]内存泄漏解决

     下面就将Alamofire 在PUT、POST请求下body 传值以及图片、文件上传的调用简单二次封装列出如下,供参考和学习使用:

  • 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)
                        }
                    }
        }
    }
  • Alamofire实现OAuth Password 网络请求案例:
///  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不存在")
                        }
                    }
        }
    }
  • Alamofire文件或图片上传,参考案例:
/**!
     * 文件或图片上传
     * @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
}

 

 类似资料: