美文网首页
Moya+RxSwift+HandyJson 实现网络请求及模型

Moya+RxSwift+HandyJson 实现网络请求及模型

作者: reyzhang | 来源:发表于2020-11-13 13:43 被阅读0次

    Moya架构图

    Moya架构图

    CocoaPods集成

    pod 'RxCocoa'
    pod 'RxSwift'
    
    pod 'Moya/RxSwift'
    pod 'HandyJSON'
    

    Moya简单使用

    1.定义枚举,存储网络请求
    // 定义一个枚举,存放我们的网络请求
    enum MemberApi {
        case login(username:String,password:String,token:String)
    }
    
    2. 实现moya的TargetType协议
    extension MemberApi:TargetType{
    
        //api 接口基地址
        var baseURL: URL {
            return URL.init(string: BaseURL)!
        }
    
        //请求路径
        var path:String{
            switch self {
            case .login(username: _, password:_ , token:_):
                return "login/accountLogin"
            }
        }
    
    
        var headers: [String: String]? {
            return nil;
        }
    
        //请求的参数
        var parameters: [String: Any]? {
            switch self {
            case .login(username: let userName, password: let pwd, token: let token):
                return ["account":userName,"pwd":pwd,"deviceToken":token];
            }
        }
    
    
        ///请求方式
        var method: Moya.Method {
            switch self {
            case .login(username: _, password: _, token: _):
            return .post;
            }
        }
    
        /// The method used for parameter encoding.
        var parameterEncoding: ParameterEncoding {
            return URLEncoding.default
        }
    
        /// Provides stub data for use in testing.
        var sampleData: Data {
            return "".data(using: String.Encoding.utf8)!
        }
    
        //MARK:task type
        var task: Task {
           return .requestPlain
        }
    
        var validate: Bool {
            return false
        }
    
    }
    
    3. 发起网络请求
    let provider = MoyaProvider<MemberApi>();
    
    provider.request(.login(username: "haha", password: "123456", token: "qwe")) { (result) in
         if result.error == nil{
             LLog(result.value);
         }
    }
    

    模型转换

    首先, 我们需要处理Moya请求返回Moya.Response对象, 在返回给客户端时我们需要将Moya.Response映射成相应的模型对象。
    其次, 我们希望使用RxSwift的链式写法来完成字典到模型的转换。

    基于如上两点: 我们需要做如下两步处理。
    1.扩展RxSwift 的 Observable 协议给其添加mapModel方法,传入要映射的模型类型
    2.需要将Moya.Response对象映射成相应的模型对象,这里配合使用HandyJSON库

    代码如下:

    ///定义在处理过程中可能出现的Error
    enum RxSwiftMoyaError: String {
        case ParseJSONError   ///解析json时出错
        case OtherError       ///其他错误  
        case ResponseError    ///返回的结果有错
        case RequestFailedError ///请求返回错误 (根据请求码判断)
    }
    
    ///让其实现Swift.Error 协议
    extension RxSwiftMoyaError: Swift.Error { }
    
    
    ///扩展 RxSwift的Observable协议,添加mapModel方法
    extension Observable {
    
        func mapModel<T: HandyJSON>(_ type: T.Type) throws -> Observable<T> {
            return map { response in
    
                ///判断Response类型
                guard let response = response as? Moya.Response else {
                    throw RxSwiftMoyaError.ResponseError
                }
                
                ///判断请求码
                guard (200...209) ~= response.statusCode else {
                    throw RxSwiftMoyaError.RequestFailedError
                }
                
                ///转json
                guard let json = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions.init(rawValue: 0)) as! [String: Any] else {
                    throw RxSwiftMoyaError.ResponseError
                }
                
    
                ///使用HandyJSON库,映射成指定模型
                let object = JSONDeserializer<T>.deserializeFrom(dict: json)
                guard let model = object else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
                return model
            }
        }
    }
    

    使用:

    ///初始化一个MoyaProvider, 其中MemberApi为使用了TargetType协议的enum枚举
    let mp = MoyaProvider<MemeberApi>()
    let ob = mp
    .rx.request(type)  /// rx.request 为Moya/RxSwift 库中提供的扩展实现,返回的是一个Single类型
    .asObservable()  ///需要使用asObservable将Single类型转成Observable
    .mapModel(UserInfo.self) ///将请求返回结果进行映射
    

    网络请求的处理过程大致如上,代码中只有有网络请求的地方就会有如下代码,所以这块代码的调用我们再把它封装一下。

    final class NetworkTools {
        
        static func request<H: HandyJSON, T: TargetType>(_ type:T, _ model: H.Type) -> Observable<H> {
            
            let mp = MoyaProvider<T>()
    
            let ob = mp
                .rx.request(type)  ///type 实现T类型协议的具体对象
                .asObservable()
                .mapModel(model)
            
            return ob
        }
    }
    
    
    ///使用
    NetworkTools.request(MemberApi.login(username: "haha", password: "123456", token: "qwe"), UserInfo.self)
    .subscribe(onNext:{   ///订阅
        
    })
    

    最后

    针对网络层的封装,在如下的Demo中又做了演进,如果感兴趣,请移步至项目 TestProject 中查看

    相关文章

      网友评论

          本文标题:Moya+RxSwift+HandyJson 实现网络请求及模型

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