use MultiTarget for multiple targets (高级用法--使用MultiTarget)--Moya文档

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()

然后把请求

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(_ 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 { }

你可能感兴趣的:(use MultiTarget for multiple targets (高级用法--使用MultiTarget)--Moya文档)