美文网首页
RxSwift+Moya之网络请求

RxSwift+Moya之网络请求

作者: iOS_我更专业 | 来源:发表于2021-05-13 16:17 被阅读0次

    一、认识

    RxSwift:函数式响应编程的框架

    Moya :是一个基于 Alamofire 的更高层网络请求封装抽象层

    二、实践

    1、创建API枚举类:

    enum API {

        ///检查版本

        case checkVersion(nowVer:String)

    }

    API需要遵从 TargetType 的协议,且需要实现的方法如下:

        //服务器地址

        var baseURL:URL{}

        //各个请求的具体路径

        varpath:String{}

        //请求任务事件(这里附带上参数)

        var task:Task{}

        //请求类型

        var method:Moya.Method{}

        //做单元测试模拟的数据

        var sampleData: Data {}

        //请求头

        var headers: [String:String]? {}

    2、Moya的扩展

    extension PrimitiveSequence where Trait == SingleTrait, Element == Response {

        /// 序列化成遵守Codeable协议的对象

        ///

        /// - Parameter type: 需要序列化Data的类型

        /// - Returns: 返回RxSwift的Signle类型

        func map(_type:D.Type) ->Single {

            return flatMap{ response ->Singlein

                do{

                    let successfulResponse = try response.filterSuccessfulStatusCodes()

                    let model =tryJSONDecoder().decode(D.self, from: successfulResponse.data)

                    return Single.just(model)

                }catch{

                    throw MoyaError.underlying(error, response)

                }

            }

        }

    }

    extension PrimitiveSequence where Trait == SingleTrait, Element: Codable & TestResponse {

        /// 验证接口返回的code是否为指定的值(默认为0)

        func validate(code:Int=0) ->Single {

            return flatMap{ response ->Singlein

                guard response.Code==nilelse{

                    throw MoyaError.underlying(NSError(domain:"com.Abitofcomedy.error",

                                                       code:-1,

                                                       userInfo: [NSLocalizedDescriptionKey: response.Message??"未知错误"]),

                                               nil)

                }

                returnSingle.just(response.data)

            }

        }

    }

    3、Base Model类

    protocol TestResponse {

        associatedtype ResponseDataType

        var Code:Int? {get}

        var Message:String? {get}

        var data: ResponseDataType? { get }

    }

    struct TestModel<T: Codable>: Codable, TestResponse {

        typealias ResponseDataType = T

        let Code:Int?

        let Message:String?

        let data:T?

    }

    4、请求Manager类

    class APIManager: MoyaProvider<API> {

        static let shared=APIManager()

        private init() {

            let requestClosure = { (endpoint:Endpoint, closure:@escaping MoyaProvider.RequestResultClosure) in

                do{

                    var urlRequest =try endpoint.urlRequest()

                    urlRequest.timeoutInterval=20

                    closure(.success(urlRequest))

                }catchMoyaError.requestMapping(let url) {

                    closure(.failure(MoyaError.requestMapping(url)))

                }catch MoyaError.parameterEncoding(let error) {

                    closure(.failure(MoyaError.parameterEncoding(error)))

                }catch{

                    closure(.failure(MoyaError.underlying(error,nil)))

                }

            }

    let networkLoggerPlugin =NetworkLoggerPlugin(configuration: .init(formatter: .init(entry: { (_identifier:String,_message:String,_target:TargetType) ->String in

                return message

            }, requestData: { (data) -> (String) in

                if let string =String(data: data, encoding: .utf8) {

                    return "\n\n    \(string.replacingOccurrences(of:"&", with:"\n    "))\n"

                }else{

                    return "请求信息解析错误"

                }

            }, responseData: { (data) -> (String)in

                if let string =String(data: data, encoding: .utf8) {

                    return "\n\n    \(string.replacingOccurrences(of:"&", with:"\n    "))\n"

                }else{

                    return "返回信息解析错误"

                }

            }), output: { (_target:TargetType, stringArr)in

            }, logOptions: .verbose))

            super.init(requestClosure: requestClosure, plugins: [networkLoggerPlugin])

        }

    }

    5、请求

    let disposeBag = DisposeBag()

    APIManager.shared.rx

                    .request(.checkVersion(nowVer:"1.0.0"))

                    .map(TestModel<CheckVersionModel>.self)

                    .validate()

                    .subscribe(onSuccess: { (model)in

                        //成功获取 CheckVersionModel 

                        //注:CheckVersionModel 继承 Codable 即可

                    }, onError: { (error)in

                        //失败

                    })

                    .disposed(by:disposeBag)

    三、总结

    这样对于请求的封装可能有一些深,但是这样代码的抽离,在Controller层(MVC)或者ViewModel层(MVVM)都会使代码减少很多,业务层的代码也能更好的在链式响应式编程中得以体现...

    未完待续~

    相关文章

      网友评论

          本文标题:RxSwift+Moya之网络请求

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