美文网首页
Swift Alamofire与Moya的结合使用

Swift Alamofire与Moya的结合使用

作者: Tomboy_Anan | 来源:发表于2021-09-14 14:20 被阅读0次

前提先熟悉Alamofire的基本使用

Swift 的 Alamofire 与 Objective-C 的 AFNetwork 使用方法 大同小异,相信从 OC 刚转为 Swift 的也能很快上手

Moya 结合 Alamofire 的快速上手

通过 Cocoapods 安装后, 几乎就不用直接使用Alamofire 了.
新建一个网络请求工具类,
定义请求超时的时间

//设置请求超时时间
let requestTimeoutClosure = { (endpoint: Endpoint, done: @escaping MoyaProvider<NetworkAPI>.RequestResultClosure) in
    do {
        var request = try endpoint.urlRequest()
        request.timeoutInterval = 30
        done(.success(request))
    } catch {
        ProgressHUDManager.dismiss()
        return
    }
}

声明一个全局的实体属性, 传入设置好的超时时间

let NetworkProvider = MoyaProvider<NetworkAPI>(requestClosure: requestTimeoutClosure)

通过 enum 的方式自定义api接口

/// 无论是 POST 或者 GET 请求 都按照以下方式定义, 需要参数的带上参数
enum NetworkAPI {
    /// 重置密码
    case resetPassword(tel: String,code:String,password: String)
    /// 获取用户信息
    case getUserInfo
}

给 enum 写一个分类 继承 TargetType

extension NetworkAPI: TargetType {
    /// 定义 BaseUrl  将自动与 path 相结合
    var baseURL: URL {
        return URL(string: BASEURL)!
    }

    /// 针对不同请求的路径
    var path: String {
        switch self {
        case .resetPassword(_, _, _):
            return "/xxxxxxx/oracle/xxxxxx/reset_password"
        case .getUserInfo:
            return  "/xxxxxxx/oracle/xxxxx/user_info"
        }
    }
  /// 设置请求的 的类型. Get 或者是 POST
  /// 例子中 getUserInfo 是 get 请求, 重置密码是 POST
    var method: Moya.Method {
        switch self {
        case .getUserInfo,
            return .get
        default:
            return .post
        }
    }

    // 请求任务事件(这里附带上参数)
    var task: Task {
      /// 定义封装参数的字典
        var parmeters: [String : Any] = [:]
        switch self {
        /// 这里展示Get 请求有参数需要拼接时 如何拼接参数.
        case .getPhoneNumberCode(let str):
            return "xxxxx/oracle/xxxxx/register/\(str)"
        /// 这里展示 Get 请求 没有参数需要拼接时 直接break. 使用return 的 .requestPlain 形式发送请求
        case .getUserInfo,
            break
        /// POST 请求 封装参数提交请求
        case .resetPassword(let tel, let code,let password):
            parmeters = ["tel":"\(tel)",
                         "verification_code":"\(code)",
                         "password":"\(password)"]
            return .requestParameters(parameters: parmeters, encoding: JSONEncoding.default)
        }
        return .requestPlain
    }

    // 请求头 可以针对不同api 进行单独设置.
    var headers: [String : String]? {
        switch self {
      /// 以下是对 上传文件或者图片类型 进行的单独设置, 其余普通请求如无特殊要求. 默认即可
        case .saveModifyUserInfo:
            return ["Content-type":"multipart/form-data",
                    "Content-Disposition":"form-data",
                    "Content-Type":"application/json;charset=utf-8"]
        default:
            return nil
        }
    }

    // 是否执行Alamofire验证
    var validate: Bool {
        return false
    }

    // 这个就是做单元测试模拟的数据,只会在单元测试文件中有作用
    var sampleData: Data {
        return "{}".data(using: String.Encoding.utf8)!
    }

} 

上传图片和其他文件操作

/// Task 请求任务事件中,和普通的 GET POST 请求不同
  case .saveModifyUserInfo(let nickname,let description, let tel, let file, let fileName):
            let nicknameData = nickname.data(using: .utf8)
            let nameData = MultipartFormData(provider: .data(nicknameData!), name: "nickname")

            let descriptionData = description.data(using: .utf8)
            let descriptionData1 = MultipartFormData(provider: .data(descriptionData!), name: "description")

            let telData = tel.data(using: .utf8)
            let telData1 = MultipartFormData(provider: .data(telData!), name: "tel")

            let formData = MultipartFormData(provider: .data(file!), name: "file",
                                             fileName: fileName, mimeType: "application/octet-stream")
            let multipartDataArr = [nameData,descriptionData1,telData1,formData]
            return .uploadMultipart(multipartDataArr) 

调用

NetworkProvider.request(NetworkAPI.login(tel: self.phoneTextfield.text, password:self.passwordTextfield.text)) { [weak self] (result) in
    ProgressHUDManager.dismiss()
    if case .success(let response) = result {
        do {
            let jsonDic = try response.mapJSON() as! NSDictionary
            if jsonDic.value(forKey: "err_code") != nil {
                let code = jsonDic["err_code"] as! String
                if code == "0" {
                    ProgressHUDManager.showSuccessWithStatus("登录成功")
                   // let resultDic = jsonDic["result"] as? NSDictionary
                    self?.navigationController?.popToRootViewController(animated: true)
                } else  {
                    ProgressHUDManager.showErrorWithStatus(networkErrorCode(code))
                }
            }
        } catch {
            ProgressHUDManager.showErrorWithStatus("请求错误")
        }
    } else {
        ProgressHUDManager.showErrorWithStatus("请求失败")
    }
} 

Alamofire 与 Moya 简单结合使用完毕

另外

每一次请求的响应信息如果是固定的. 可以对以上发起请求 解析步骤再进行一次封装

class Request {
   
    public static var sharedInstance : NFTRequest {
        struct Static {
            static let instance : NFTRequest = NFTRequest()
        }
        return Static.instance
    }

    func requestWithApi(_ api:NetworkAPI,resutBlock:@escaping(_ result: Any?, _ code: String?)->()){
        NetworkProvider.request(api) { (result) in
            if case .success(let response) = result {
                do {
                    let jsonDic = try response.mapJSON() as! NSDictionary
                    guard jsonDic.value(forKey: "err_code") != nil else {
                        ProgressHUDManager.showErrorWithStatus(ERROR_RESPONSE)
                        return
                    }
                    let code = jsonDic["err_code"] as! String
                    if code == "0" {
                        resutBlock(jsonDic["result"], code)
                    } else {
                        resutBlock(nil, code)
                        /// 需要登录的错误 在外面实现弹窗提示即可
                        if code != "2" {
                            ProgressHUDManager.showFailWithStatus(networkErrorCode(code))
                        }
                    }
                } catch {
                    print("解析 失败:  response: \(response) \n api:\(api)")
                    ProgressHUDManager.showErrorWithStatus(ERROR_RESPONSE)
                }
            } else if case .failure(let error) = result {
                print("请求失败  result: \(result) \n api:\(api) --- \n\(error)")
                resutBlock(nil, "-1009")
                ProgressHUDManager.showErrorWithStatus(ERROR_REQUEST)
            }
        }
    }
}

在外调用时就相对简洁. 不需要频繁的解析和判断数据

Request.sharedInstance.requestWithApi(NetworkAPI.getUserInfo) { (result, code) in
        if result != nil {
            let dic = result as! NSDictionary
            self.userModel = UserModel.deserialize(from: dic)!
         } else if code == "2" {
            /// 服务器返回需要登录的错误, 自动登录处理. 
            self.againLogin { (state) in
            if state == "1" {
                 self.getUserInfoDataFunc()
             } else {
                ProgressHUDManager.showErrorWithStatus(networkErrorCode(code!))
                let vc = LoginViewController()
                self.navigationController?.pushViewController(vc, animated: true)
                  }
                }
            }
        } 

相关文章

网友评论

      本文标题:Swift Alamofire与Moya的结合使用

      本文链接:https://www.haomeiwen.com/subject/ruhcgltx.html