美文网首页swift学习资料
RxSwift + Moya + ObjectMapper  构

RxSwift + Moya + ObjectMapper  构

作者: 九龙 | 来源:发表于2019-03-14 15:38 被阅读0次

    demo地址
    单独的我就不多介绍了直接看github
    RxSwift
    Moya
    ObjectMapper

    cocoaPods只安装上面的三个库是不够的,需要安装带有RxSwift扩展的库,如下:

    pod 'RxSwift',    '~> 4.3.1'
    pod 'RxCocoa',    '~> 4.3.1'
    pod 'Moya/RxSwift'
    pod 'RxDataSources', '~> 3.1.0'
    pod 'Moya-ObjectMapper/RxSwift'
    

    1.在模块里面建立一个文件夹,里面新建一个API文件如图

    import Moya
    import Alamofire
    
    public enum ExampleAPI {
        //获取年检详细信息
        case getExampleInfo(id:Int)
    }
    
    extension ExampleAPI:TargetType {
        
        public var path: String {
            switch self {
            case .getExampleInfo:
                return "/example/info"
            }
        }
        
        public var method: Moya.Method {
            switch self {
            case .getExampleInfo:
                return .get
            }
        }
        
        public var sampleData: Data {
            return "{}".data(using: String.Encoding.utf8)!
        }
        
        public var task: Task {
            switch self {
            case let .getExampleInfo(id: id):
                return .requestParameters(parameters: ["id": id], encoding: URLEncoding.default)
            }
        }
        
        public var headers: [String : String]? {
            return ["uid": "456", "token": "123"]
        }
        
        public var baseURL: URL {
            return UtimesBaseURL
        }
    }
    
    

    2.模型文件

    import ObjectMapper
    
    struct ExampleInfo:Mappable {
        var cost:Int = 0                        //年检费用 ,
        var rule:String = ""                        //规则
        
        var timeDate:String = ""                   //年检到期时间
        var timeRemain:Int = 0                      //剩余到期天数
        var timeYear:String = ""                  //年检年数
        
        var feeText:String {
            return String(format: "¥ %0.2f", CGFloat(CGFloat(cost)/CGFloat(100)))
        }
        
        init?(map: Map) {}
        
        mutating func mapping(map: Map) {
            cost <- map["cost"]
            rule <- map["rule"]
            timeDate <- map["time_date"]
            timeRemain <- map["time_remain"]
            timeYear <- map["time_year"]
        }
    }
    
    

    2.全局通用的一个服务器返回的数据结构(data是一个泛型,适配不同的返回数据)

    struct ResponseNormalModel<T:Mappable>:Mappable,Error{
        
        var code : Int = defualtCode         //状态码
        var message: String = ""       //消息
        var data:T?                     //数据
        
        init?(map: Map) {}
        
        init(code:Int = defualtCode,message:String,data:T?) {
            self.code = code
            self.message = message
            self.data = data
        }
        
        mutating func mapping(map: Map) {
            code <- map["code"]
            message <- map["msg"]
            data <- map["data"]
        }
    }
    

    provider设置

    let MyProvider = JLProvider(endpointClosure: myEndpointClosure,
                                requestClosure: requestClosure,
                                stubClosure: MoyaProvider.neverStub,
                                callbackQueue: DispatchQueue.main,
                                manager: UtimesHTTPConfig.getSessionManager(),
                                plugins: [myNetworkLoggerPlugin,RequestLoadingPlugin()],
                                trackInflights: false)
    
    // MARK: - 设置请求头
    private let myEndpointClosure = { (target: MultiTarget) -> Endpoint in
        //处理URL
        let url = target.baseURL.appendingPathComponent(target.path).absoluteString
        
        let endpoint = Endpoint(url: url,
            sampleResponseClosure: { .networkResponse(200, target.sampleData) },
            method: target.method,
            task: target.task,
            httpHeaderFields: target.headers
        )
        
        do {
            //设置通用header
            var urlRequest = try endpoint.urlRequest()
            urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: publicParameters, options: .prettyPrinted)
        } catch let error  {
            print(error)
        }
        return endpoint.adding(newHTTPHeaderFields: [ "Content-Type" : "application/json",])
        
    }
    
    // MARK: - 设置请求超时时间
    private let requestClosure = { (endpoint: Endpoint, closure: @escaping MoyaProvider<MultiTarget>.RequestResultClosure) in
        do {
            var urlRequest = try endpoint.urlRequest()
            urlRequest.timeoutInterval = 12
            closure(.success(urlRequest))
        } catch MoyaError.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)))
        }
    }
    
    // MARK: - 调试plugin
    let myNetworkLoggerPlugin = NetworkLoggerPlugin(verbose: true, output: reversedPrint, responseDataFormatter: { (data: Data) -> Data in
        do {
            let dataAsJSON = try JSONSerialization.jsonObject(with: data)
            let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
            return prettyData
        } catch {
            return data
        }
    })
    
    func reversedPrint(_ separator: String, terminator: String, items: Any...) {
        #if DEBUG
        guard shouldShowLog else { return }
        for item in items {
            print(item, separator: separator, terminator: terminator)
        }
        #endif
    }
    
    let shouldShowLog = true  //是否打印日志
    
    
    //MARK: - 自定义Provider
    import ObjectMapper
    import RxSwift
    
    class JLProvider: MoyaProvider<MultiTarget> {
        
        let disposeBag:DisposeBag = DisposeBag()
        
        override init(endpointClosure: @escaping MoyaProvider<Target>.EndpointClosure, requestClosure: @escaping MoyaProvider<Target>.RequestClosure, stubClosure: @escaping MoyaProvider<Target>.StubClosure, callbackQueue: DispatchQueue?, manager: Manager, plugins: [PluginType], trackInflights: Bool) {
            super.init(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, callbackQueue: callbackQueue, manager: manager, plugins: plugins, trackInflights: trackInflights)
        }
    }
    
    extension JLProvider{
        func request<T:Mappable,U:TargetType>(target:U)-> Observable<T>{
            return self.rx.request(target as! MultiTarget)
                .filterSuccessfulStatusCodes()
                .asObservable()
                .filterSuccess(disposeBag: disposeBag, target: target as! MultiTarget)
                .mapObject(T.self)
        }
    }
    
    
    

    service文件

    import SwiftyJSON
    import RxSwift
    import Moya
    
    struct ExampleService {
        let disposeBag:DisposeBag = DisposeBag()
        
        func getExampleInfo(id:Int) -> Observable<ResponseNormalModel<ExampleInfo>> {
            let target = MultiTarget(ExampleAPI.getExampleInfo(id: id))
            return MyProvider.request(target: target)
        }
    }
    

    调用

     ExampleService().getExampleInfo(id: id)
                .subscribe(onNext: { [weak self](model) in
                    //处理返回的数据
                }, onError: { [weak self](error) in
                    //处理返回的错误
                }).disposed(by: disposeBag)
    

    以上就是大概的4个流程

    request里面的.filterSuccess(disposeBag: disposeBag, target: target)是处理token过期,让app在后台自动更新token 用户无感的moya plugin,下篇文章详解

    相关文章

      网友评论

        本文标题:RxSwift + Moya + ObjectMapper  构

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