美文网首页
use MultiTarget for multiple tar

use MultiTarget for multiple tar

作者: 心印印心 | 来源:发表于2017-06-29 20:46 被阅读0次

    Advanced usage - use MultiTarget for multiple targets using the same Provider(高级用法--使用MultiTarget(为多个target使用同样的Provider)

    当你有很多个endpoints时,你可能会得到一个很长的provider并且在几百个case里面切换.当然,你可以把这些逻辑分割到多个target中,但你不得不使用多个providers.这会使你的app逻辑复杂化,如果你想为每个provider使用相同的plugins/closures,需要额外的工作来管理它.然而,我们可以使用MutiTarget这个内置枚举,它可以很容易的使用,而且能帮我们解决上面的问题.

    首先,我们定义一个将使用多个target的provider

    let provider = MoyaProvider<MultiTarget>()
    

    然后把请求

    provider.request(.zen) { result in
    // do something with `result`
    }
    

    替换成

    provider.request(MultiTarget(GitHub.zen)) { result in
    // do something with `result`
    }
    

    改造完毕!相当的简单.如果你有很多想分割的endpoint---这将是一个完美的解决方法.如果你想看这个API,请查看Demo,它有两个target:一个是Demo(使用Moya的基本形式),一个是DemoMultiTarget(使用编辑版的MutiTarget形式)

    Multiple targets when using associatedtype(在Mutiple target中使用关联类型)

    当调用一个网络请求时,Moya可以让你静态的验证参数。你有可能想扩展Moya的TargetType来验证自定义的类型。其中一种情况如在request请求中基于各种请求返回各种序列化对象,而不是直接返回MoyaResponse。这种需求可以通过向TargetType中添加associatetype来完成。

    protocol DecodableTargetType: Moya.TargetType {
        associatedType ResultType: SomeJSONDecodableProtocolConformance
    }
    
    enum UserApi: DecodableTargetType {
        case get(id: Int)
        case update(id: Int, name: String)
        ...
    
        var baseURL: URL { ... }
        var path: String { switch self ... }
        var method: Moya.Method { ... }
    
        typealias ResultType = UserModel
    }
    

    因为associatedtype,所以MultiTarget不能被当做DecodableTargetType类型(ps:因为它MultiTarget源码实现没有实现这个扩展协议)。所以我们需要使用MultiMoyaProvider的变体。它不需要一个泛型参数(经过查看相关issue话题,这个作者考虑后的设计,推荐强类型)。因此,请求可以被调用并且任何遵循TargetType协议的实例对象都可以作为参数。使用MultiMoyaProvider允许你使用关联类型来编写及包装请求

    例如,我们可以创建一个requestDecoded方法并返回ResultType而不是直接返回MoyaResponse。

    extension MultiMoyaProvider {
        func requestDecoded<T: DecodableTargetType>(_ target: T, completion: @escaping (_ result: Result<[T.ResultType], Moya.Error>) -> ()) -> Cancellable {
            return request(target) { result in
                switch result {
                case .success(let response):
                    if let parsed = T.ResultType.parse(try! response.mapJSON()) {
                        completion(.success(parsed))
                    } else {
                        completion(.failure(.jsonMapping(response)))
                    }
                case .failure(let error):
                    completion(.failure(error))
                }
            }
        }
    }
    

    这个代码的优美之处在于,它的回调中的输入类型隐式的由传入的target类型决定

    你可以传递任何DecodableTargetType来启动请求

    let provider = MultiMoyaProvider()
    provider.requestDecoded(UserApi.get(id: 1)) { result in
        switch result {
        case .success(let user):
          // type of `user` is implicitly `UserModel`. Using any other type results
          // in compile error
          print(user.name)
        }
    }
    

    当使用关联类型时,你将不得不为各种的target定义各种不同的类型。比如,我们有一另外一个target--SessionApi

    struct SessionApi: DecodableTargetType {
        typealias ResultType = SessionModel
    }
    

    它有不同的ResultType。但我们可以使用MultiMoyaProvider的同一个实例对象:

    provider.requestDecoded(SessionApi.get) { result in
        switch result {
        case .success(let session):
            // type of `user` is implicitly `SessionModel` here
        }
    }
    

    总结 这小节的核心:

    1. 当TargetType的实现里面的API太多了,需要分割成多个独立的TargetType,而常规使用MoyaProvider来创建请求就会变得庞大了。所以MutiTarget乘时而生。
    2. MutiTarget的使用
    3. 在MutiTarget中如何使用关联类型。(关键是扩展MultiMoyaProvider,例如一个返回结果的模型序列化的实现)

    ps: 没有找到MultiMoyaProvider,自己推断它就是MoyaProvider??
    经过搜索Moya github issue 找到个 [WIP] MoyaProvider variant without generic parameter #910
    对于实现为 class MultiMoyaProvider: MoyaProvider<MultiTarget> { }

    相关文章

      网友评论

          本文标题:use MultiTarget for multiple tar

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