网络请求框架Moya使用一

一、安装 Moya(CocoaPods)

pod "Moya/RxSwift”

pod “HandyJSON”

二、基本用法

1、实现  TargetType  协议

2、实现  PluginType 插件协议

3、扩展 ObservableType 解析 JSON 数据

//MoyaProvider

import Foundation

import Moya

//Provider

let requestProvider = MoyaProvider(plugins: [RequestLoadingPlugin()])

//Hud Provider

let requestHudProvider = MoyaProvider(plugins: [RequestLoadingPlugin(true)])

enum RequestManagerProvider {

    //密码登录

    case LoginPassword(mobile:String, password:String)

    //注册

    case Register(mobile:String, password: String, code: String)

    //忘记密码

    case ForgetPassword(mobile:String, code: String, password: String, repassword: String)

}

extension RequestManagerProvider: TargetType {


    var baseURL: URL {

        return URL(string: "http://baseurl.com")!

    }


    //请求路径

    var path: String {

        switch self {

        case .LoginPassword:

            return "/login"

        case .Register:

            return "/register"

        case .ForgetPassword:

            return "/forgetpwd"

        }

    }

    //请求方式

    var method: Moya.Method {

        return .post

    }


    //用于单元测试

    var sampleData: Data {

        return "".data(using: String.Encoding.utf8)!

    }


    //请求接口时对应的请求参数

    var task: Task {


        switch self {

        case .LoginPassword(let mobile,let password):


            let bundleId = Bundle.main.bundleIdentifier!


            let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

            let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "password")

            let formData3 = MultipartFormData(provider: .data(bundleId.data(using: .utf8)!), name: "bundle_id")

            return .uploadMultipart([formData1, formData2,formData3])


        case .Register(let mobile, let password, let code):


            let bundleId = Bundle.main.bundleIdentifier!


            let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

            let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "password")

            let formData3 = MultipartFormData(provider: .data(code.data(using: .utf8)!), name: "code")

            let formData4 = MultipartFormData(provider: .data(bundleId.data(using: .utf8)!), name: "bundle_id")


            return .uploadMultipart([formData1, formData2, formData3, formData4])

        case .ForgetPassword(let mobile, let code, let password, let repassword):


            let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

            let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "newpassword")

            let formData3 = MultipartFormData(provider: .data(code.data(using: .utf8)!), name: "code")

            let formData4 = MultipartFormData(provider: .data(repassword.data(using: .utf8)!), name: "repassword")

            return .uploadMultipart([formData1, formData2, formData3, formData4])

        case .VerificationCode(let mobile, let event):

            let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

            let formData2 = MultipartFormData(provider: .data(event.data(using: .utf8)!), name: "event")

            return .uploadMultipart([formData1, formData2])

        case .RouteList:


            let typeid = Bundle.main.bundleIdentifier! == "com.shanhushanhu.shanhushanhu" ? "1" : "2"


            let formData1 = MultipartFormData(provider: .data(typeid.data(using: .utf8)!), name: "typeid")

            return .uploadMultipart([formData1])

        default:

            return .requestPlain

        }

    }

    //header信息

    var headers: [String : String]? {

        return ["Content-Type":"multipart/form-data"]

    }

}

//请求插件

import Foundation

import Moya

import iProgressHUD

class RequestLoadingPlugin: PluginType {


    var SwiftIsShowHud:Bool = false


    init(_ isShowHud: Bool = false) {

        SwiftIsShowHud = isShowHud

    }



    func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {

        print("prepare")

        var mRequest = request

        mRequest.timeoutInterval = 20

        return mRequest

    }

    func willSend(_ request: RequestType, target: TargetType) {

        print("开始请求")

        if SwiftIsShowHud == true {


            DispatchQueue.main.async {

                let keyViewController = UIApplication.shared.keyWindow?.rootViewController

                if (keyViewController != nil) {


                    iProgressHUD.sharedInstance().attachProgress(toView: (keyViewController!.view)!)

                    keyViewController!.view.showProgress()

                }

            }

        }


    }


    func didReceive(_ result: Result, target: TargetType) {

        print("结束请求")


        if SwiftIsShowHud == true {

            DispatchQueue.main.async {

                let keyViewController = UIApplication.shared.keyWindow?.rootViewController

                if (keyViewController != nil) {

                    keyViewController!.view.dismissProgress()

                }

            }

        }


//        switch result {

//        case .failure(let error):

//

//            let errorReason: String = error.errorDescription ?? ""

//            var tip = ""

//            if errorReason.contains("The Internet connection appears to be offline") {

//                tip = "网络不给力,请检查您的网络"

//            }else if errorReason.contains("Could not connect to the server") {

//                tip = "无法连接服务器"

//            }else {

//                tip = "请求失败"

//            }

//

//        default:

//            break

//        }

    }

}

//JSON 解析

import Foundation

import RxSwift

import HandyJSON

import Moya

enum DCUError : Swift.Error {

    case ParseJSONError

    case RequestFailed

    case NoResponse

    case UnexpectedResult(resultCode: Int?,resultMsg:String?)

}

enum RequestStatus: Int {

    case requestSuccess = 1

    case requestTokenError = 401

    case requestError

}

fileprivate let RESULT_CODE = "code"

fileprivate let RESULT_MSG = "msg"

fileprivate let RESULT_DATA = "data"

public extension ObservableType {

    func mapResponseToObject(type: T.Type) -> Observable {

        return map { response in

            guard let response = response as? Moya.Response

                else {

                    throw DCUError.NoResponse

            }

//            guard ((200...209) ~= response.statusCode) else {

//                throw DCUError.RequestFailed

//            }

            ////////////////////////////////////////////////////////////

//            let jsonData = try response.mapJSON() as! [String : Any]

//            if let code = jsonData[RESULT_CODE] as? String {

//                if code == "查询成功" {

//                    if let model = JSONDeserializer.deserializeFrom(dict: jsonData){

//                        return model

//                    }

//                }

//            }

            ////////////////////////////////////////////////////////////

            guard let json = try?JSONSerialization.jsonObject(with: response.data, options: .mutableContainers) as? [String:Any] else {

                throw DCUError.NoResponse

            }            


            if let code = json[RESULT_CODE] as? Int {

                if code == RequestStatus.requestSuccess.rawValue {

                    let data = json[RESULT_DATA]


                    let objects = JSONDeserializer.deserializeFrom(dict: data as? Dictionary)


                    if objects != nil {

                        return objects!

                    }


                    if let data = data as? Data {

                        let jsonString = String(data: data,encoding: .utf8)

                        let object = JSONDeserializer.deserializeFrom(json: jsonString)



                        if object != nil {

                            return object!

                        }else {

                            return T()

//                            throw DCUError.ParseJSONError

                        }

                    }else {

                        return T()

//                        throw DCUError.ParseJSONError

                    }

                }else if code == RequestStatus.requestTokenError.rawValue {

                    // Tocken失效 跳转登录

                    VPNUserManager.sharedInstance().removeUserInfo()

                    NotificationCenter.default.post(name: NotificationName_Login, object: nil)


                    throw DCUError.UnexpectedResult(resultCode:json[RESULT_CODE] as? Int, resultMsg: nil)

                }else {

                    throw DCUError.UnexpectedResult(resultCode:json[RESULT_CODE] as? Int, resultMsg: json[RESULT_MSG] as? String)

                }

            }else {

                throw DCUError.ParseJSONError

            }


        }

    }


    func mapResponseToObjectArray(type: T.Type) -> Observable<[T]> {

        return map { response in


            // 得到response

            guard let response = response as? Moya.Response else {

                throw DCUError.NoResponse

            }


            // 检查状态码

//            guard ((200...209) ~= response.statusCode) else {

//                throw DCUError.RequestFailed

//            }


            guard let json = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? [String: Any]  else {

                throw DCUError.NoResponse

            }


            // 服务器返回code

            if let code = json[RESULT_CODE] as? Int {

                if code == RequestStatus.requestSuccess.rawValue {

                    guard let objectsArrays = json[RESULT_DATA] as? NSArray else {

                        throw DCUError.ParseJSONError

                    }

                    // 使用HandyJSON解析成对象数组

                    if let objArray = JSONDeserializer.deserializeModelArrayFrom(array: objectsArrays) {

                        if let objectArray: [T] = objArray as? [T] {

                            return objectArray

                        }else {

                            return [T]()

                        }

                    }else {

                        return [T]()

                    }


                }else if code == RequestStatus.requestTokenError.rawValue {

                    // Tocken失效 跳转登录

                    VPNUserManager.sharedInstance().removeUserInfo()

                    NotificationCenter.default.post(name: NotificationName_Login, object: nil)

                    return [T]()

                } else {

                    throw DCUError.UnexpectedResult(resultCode: json[RESULT_CODE] as? Int , resultMsg: json[RESULT_MSG] as? String)


                }

            } else {

                throw DCUError.ParseJSONError

            }

        }

    }

}

//调用

requestProvider.rx.request(.LoginPassword(mobile: mobile, password: password)).asObservable()

                .mapResponseToObject(type: VPNLoginResultMode.self)

                .subscribe(onNext: { (model) in


                     self.view.dismissProgress()


                    if let token = model.userinfo?.token {

                        VPNUserManager.sharedInstance().saveUserInfo(mobile: mobile,tocken: token)


                        GYHUD.flash(.success, title: "登录成功", onView: self.view, delay: 1) {


                            self.dismiss(animated: true) {}

                        }

                    }

                },onError: { (error) in

                    self.view.dismissProgress()


                    switch error {

                    case DCUError.UnexpectedResult(_,let resultMsg):

                        if let msg = resultMsg { GYHUD.flash(.label, title: msg, onView: self.view, delay: 1.5) }

                    default:

                        GYHUD.flash(.label, title: "请求网络失败!", onView: self.view, delay: 1.5)

                    }


                }).disposed(by: disposeBag)

你可能感兴趣的:(网络请求框架Moya使用一)