Moya + ObjectMapper 扩展及封装

    Moya 是一个基于Alamofire的 面向协议 插件化的 网络库,调用者可以通过实现TargetType协议和方便的发起网络调用,而且可以根据不同的需要定制各种插件进行初始化。

    但是在实际使用过程中仍有一些个问题

1 TargetType 协议变量太多,调用方实际只主要关心 task, path 这两个,  BaseUrl不应该暴露给调用方,这些都可以通过扩展TargetType 来实现,但是若想加入其它功能,比方说加入缓存功能,加入token,或者加入大量公共参数,这些该如何实现,怎么实现比较好?

2 Moya 网络返回的是Moya.Response 类型的数据,实际开发中大量使用自定义的Struct 作为 数据类型,虽然有ObjectMapper 可以很方便的做数据转换,但每次都要在闭包里做一次转换,可以直接返回一个Struct对象不是更好吗?

     解决办法 

1  继承TargetType, 创建一个新的Target协议, 加入自定义参数,同时隐藏不必要参数,比如想加入缓存功能,

     1 先定义缓存协议

publicenumRequestCachePolicy{

    /// 忽略缓存,仅加载网络数据

    casereloadIgnoringLocalCacheData

    /// 只加载缓存数据

    caseretutnCacheDataDontLoad

    /// 先加载缓存然后网络数据

    caseretutnCacheDataThenLoad

}

public protocol CacheType {

    // 是否需要缓存

    varneedCache:Bool{get}

    // 缓存资源的标示

    varcacheId: () ->String{get}

    // 加载缓存策略

    varcachePolicy:RequestCachePolicy{get}

}

 2  创建新的TargetType, 并且加入自定义参数,同时 

public protocol XLTargetType: TargetType, CacheType, AccessTokenAuthorizable{

    /// 具体业务参数

    varparameters: [String:Any]? {get}

}

3 重写MoayProvider 支持缓存功能

  详见 Github

2 第二个问题,有三个思路

   1  扩展Moya.Response类型,增加转换函数,这是基础,每次请求后多家一行转换函数

       funcmapCommonModel()throws->T{

        do{

            letjsonObj =  tryJSONSerialization.jsonObject(with:data, options: .allowFragments)

            letobject =Mapper().map(JSONObject: jsonObj)


            ifobject ==nil{

                throwYLError.mapNilError

            }


            returnobject!


        }catchYLError.mapNilError  {

            throwYLError.mapNilError

        }catch{

            throwYLError.responseError

        }

    }

   2 将返回的数据类型做成 associatedtype 定义在新建的TargetType中,并重写MoyaProvider,这样请求直接返回的就是关联类型指定的数据类型, 但这样会造成另外一个问题:没有办法批量写Api代码,毕竟每个TargetType协议只支持一个associatedtype

public protocol YLTargetType: TargetType, CacheType, AccessTokenAuthorizable{

    /// 返回数据类型, 这种写法理论上没问题,但实际用起来很麻烦,没办法批量组织api

    associatedtyperesponseModelType:Mappable

    /// 具体业务参数

    varparameters: [String:Any]? {get}

}

// 调用

let provider = DataProvider()    

 let sequence1 = provider.rx.requestModel(.home)

  let sequence2 = provider.rx.requestResult(.home)

3 将数据类型做成provider.request() 函数的泛型,这样也可以直接返回数据类型, 这也是最好的一种

publicprotocolXLProviderType:AnyObject{

    associatedtype Target: XLTargetType

    funcrequest(_target:Target, callbackQueue:DispatchQueue?, progress:Moya.ProgressBlock?, completion:@escaping(_result:Result,_isCache:Bool) ->Void) ->Cancellable

}

// 调用

  let provider = XLProvider()      

let userSequence = provider.rx.requestResult(.user) as Observable>

 详见Github

 最后 

    第三方虽然好用,但是对第三方包装一层仍然是必要的,

1   万一没有,发生AF2.0 到 AF3.0哪样的重大变动,那就炸了 

2  第三方通用性太好,但不贴近实际项目,根绝实际需求自定制一下,对于开发者会友好的多,

3  面向协议和插件化是网络库最好的选择,  关于插件没有细说,代码里有

你可能感兴趣的:(Moya + ObjectMapper 扩展及封装)