Moya官方文档翻译

原文地址:https://github.com/Moya/Moya/tree/master/docs
参考文章:http://www.jianshu.com/p/c1494681400b

Endpoints功能翻译

endpoint是Moya用来推断最终将要进行的网络请求的半内部数据结构。 endpoint存储以下数据:

  • The url.
  • The HTTP method (GET, POST, etc).
  • The request parameters.
  • The parameter encoding (URL, JSON, custom, etc). 参数编码
  • The HTTP request header fields. 请求头
  • The sample response (for unit testing). 测试数据返回

Providers将Targets的数据解析Endpoint里面,再将Endpoint解析到实际的网络请求中.
这里有两种方式和Endpoint交互
1.当创建provider时,可以指定从Target到Endpoint的映射方式。
2.当创建provider时,可以指定从Endpoint到URLRequest的映射方式。
第一条类似于以下内容

let endpointClosure = { (target: MyTarget) -> Endpoint<MyTarget> in
    let url = target.baseURL.appendingPathComponent(target.path).absoluteString
    return Endpoint(url: url, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, parameters: target.parameters)
}

这实际上是Moya提供的默认实现。 如果您需要某些自定义内容,例如,如果您的API需要自定义参数解析,或者如果您要创建一个在单元测试中返回非200 HTTP状态的测试提供程序,这就是你可以修改的地方。
第二种使用是非常罕见的。 Moya试图阻止你不必担心低级细节。如果你需要它也可以进行修改。 其使用在下面进一步描述。
让我们来看一个提供从Target到Endpoint灵活解析的示例。

从Target 到 Endpoint

默认情况下,Endpoint实例使用URLEncoding.default类型参数编码。 您可以在设置提供程序时使用endpointClosure中的Endpoint初始值设置的可选parameterEncoding参数指定在endpointClosure中逐个目标地编码参数的方式。
有三种参数编码类型:URL编码,JSON编码,PropertyList编码,它直接映射到Alamofire中的相应类型.每个类型都有.default属性,它给你一个特定的ParameterEncoding类型的默认实例。此外,如果你想创建你的自定义类型,只是实现ParameterEncoding协议就可以了.通常你只是想要URLEncoding.default,但你可以使用你喜欢的。这些直接映射到Alamofire参数编码。 如果你想获得关于ParameterEncoding类型的更多信息以及如何创建自己的,请查看Alamofire的关于这个问题的文档。
您可以在此闭包中添加参数或HTTP头字段。 例如,我们可能希望在HTTP头字段中设置我们的应用程序名称供服务端分析

let endpointClosure = { (target: MyTarget) -> Endpoint<MyTarget> in
    let defaultEndpoint = MoyaProvider.defaultEndpointMapping(target)
    return defaultEndpoint.adding(newHttpHeaderFields: ["APP_NAME": "MY_AWESOME_APP"])
}
let provider = MoyaProvider<GitHub>(endpointClosure: endpointClosure)

这也意味着您可以向部分或所有endPoint提供额外参数。 例如,假设我们需要假设的MyTarget目标的所有值的认证令牌,除了实际进行认证的目标之外。 我们可以构造类似于以下的endpointClosure。

let endpointClosure = { (target: MyTarget) -> Endpoint<MyTarget> in
    let defaultEndpoint = MoyaProvider.defaultEndpointMapping(target)

    // Sign all non-authenticating requests
    switch target {
    case .authenticate:
        return defaultEndpoint
    default:
        return defaultEndpoint.adding(newHttpHeaderFields: ["AUTHENTICATION_TOKEN": GlobalAppStorage.authToken])
    }
}
let provider = MoyaProvider<GitHub>(endpointClosure: endpointClosure)

注意我们可以依靠Moya的现有行为并扩展 - 而不是替换它。 add(newParameters :)和add(newHttpHeaderFields :)函数允许您依赖现有的Moya代码并添加您自己的自定义值。
示例响应是TargetType协议的要求。 但是它们只指定返回的数据。 目标到端点映射闭包是可以指定更多细节的地方,这对单元测试很有用。
示例响应具有以下两个值之一:

  • NetworkError,带有NSError?可选错误类型。
  • NetworkResponse,具有Int状态代码和Data返回的数据。

Request Mapping

正如我们前面提到的,这个库的目的不是真正提供一个编码框架来访问网络 - 这是Alamofire的工作.相反,Moya是一种方式来构思你对网络访问的想法,并提供编译时检查明确定义的网络目标。您已经了解了如何使用MoyaProvider初始值设定器的endpointClosure参数将Targets映射到endpoints。这让你创建一个Endpoint实例,Moya将使用它来推断网络API调用。在某些时候,该Endpoints必须解析成一个实际的URLRequest给Alamofire。这就是requestClosure参数的用途。
requestClosure是一种可选的,用来修改网络的请求的最后方式。它具有默认值MoyaProvider.DefaultRequestMapper,它只使用Endpoint实例的urlRequest属性。
此闭包接收Endpoint实例,并负责调用RequestResultClosure(Result <URLRequest,MoyaError> - > Void的简写)的参数与表示Endpoint的请求。在这里做你的OAuth签名或其他事情。因为你可以异步地调用闭包,你可以使用你喜欢的任何认证库(例子)。除了修改请求,你可以简单地记录它。

let requestClosure = { (endpoint: Endpoint<GitHub>, done: MoyaProvider.RequestResultClosure) in
    var request = endpoint.urlRequest

    // Modify the request however you like.

    done(.success(request))
}
let provider = MoyaProvider<GitHub>(requestClosure: requestClosure)

此requestClosure可用于修改特定于URLRequest的属性或向请求提供直到该请求创建成功才能知道的信息,例如Cookie设置。注意上面提到的endpointClosure不是用于这个目的或任何特定于请求的应用程序级映射。
此参数实际上对修改请求对象非常有用。 URLRequest有很多可以自定义的属性。假设您要停用所有要求的Cookie:

{ (endpoint: Endpoint<ArtsyAPI>, done: MoyaProvider.RequestResultClosure) in
    var request: URLRequest = endpoint.urlRequest
    request.httpShouldHandleCookies = false
    done(.success(request))
}

您还可以执行网络请求的日志记录,因为此闭包在请求发送到网络之前被调用。

Providers功能翻译

当使用Moya时,您通过MoyaProvider实例创建所有API请求,传递一个枚举值,指定您要调用的endpoint。 设置好您的endpoint后,您基本上设置好了基本用法:

let provider = MoyaProvider<MyService>()

经过简单的设置,你就可以开始请求了:

provider.request(.zen) { result in
    // `result` is either .success(response) or .failure(error)
}

这就是全部的了! request()方法返回一个Cancellable,它只有一个公共函数cancel(),您可以使用它来取消请求。 有关Result类型的更多信息请参阅示例
记住如何放置target和provider完全取决于你。 你可以查看Artsy的实现的例子。
但不要忘记在属性中保留它的引用。 如果它被释放,你会看到-999“cancelled”错误响应。

Advanced Usage

为了解释MoyaProvider的所有配置选项,我们将在下面的章节逐一介绍每个参数。

endpointClosure:

MoyaProvider初始化程序的第一个(可选)参数是一个endpoints闭包,它负责将枚举值映射到具体的Endpoint实例。 让我们来看看具体是什么样子。

let endpointClosure = { (target: MyTarget) -> Endpoint<MyTarget> in
    let url = target.baseURL.appendingPathComponent(target.path).absoluteString
    return Endpoint(url: url, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, parameters: target.parameters)
}
let provider = MoyaProvider(endpointClosure: endpointClosure)

注意,我们不必在MoyaProvider初始化程序中指定泛型类型,因为Swift将从我们的endpointClosure类型推断它。
这个endpointClosure就像你可以得到的一样简单。 它实际上也是默认实现,存储在MoyaProvider.defaultEndpointMapping。 查看Endpoints文档了解更多有关为什么你需要自定义这些的信息。

requestClosure:

下一个可选的初始化参数是requestClosure,它将Endpoint解析为实际的URLRequest。 再次查看Endpoints文档了解如何以及为什么这样做。

stubClosure:

下一个选项是提供一个stubClosure。 这将返回.never(默认值),.immediate或.delayed(seconds)之一,您可以将已存根的请求延迟一定的时间。 例如,.delayed(0.2)将延迟每个存根请求。 这可以很好地模拟单元测试中的网络延迟。
很好的是如果你需要不同于其他请求来存根一些请求,你可以使用自己的闭包。

let provider = MoyaProvider<MyTarget>(stubClosure: { target: MyTarget -> Moya.StubBehavior in
    switch target {
        /* Return something different based on the target. */
    }
})

但通常你想要对所有的目标执行同样的stubbing行为。 有三个类方法在MoyaProvider你可以使用代替。

MoyaProvider.neverStub
MoyaProvider.immediatelyStub
MoyaProvider.delayedStub(seconds)

所以在上面的例子中,如果你想要立即改变所有目标的stubbing行为,以下任一将起作用。

let provider = MoyaProvider<MyTarget>(stubClosure: { (_: MyTarget) -> Moya.StubBehavior in return .immediate })
let provider = MoyaProvider<MyTarget>(stubClosure: MoyaProvider.immediatelyStub)

manager

接下来就是manager参数。 默认情况下,你会得到一个基本配置的自定义Alamofire.Manager实例。

public final class func defaultAlamofireManager() -> Manager {
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders

    let manager = Alamofire.Manager(configuration: configuration)
    manager.startRequestsImmediately = false
    return manager
}

只有一个特别的事情:因为构造一个Alamofire.Request在AF将默认立即激活请求,即使单元测试的stubbing请求。 因此在Moya中,startRequestsImmediately默认设置为false。
如果您想要自定义自己的管理器,例如要添加SSL绑定,请创建一个并传递进来,所有请求将路由通过自定义配置的管理器。

let policies: [String: ServerTrustPolicy] = [
    "example.com": .PinPublicKeys(
        publicKeys: ServerTrustPolicy.publicKeysInBundle(),
        validateCertificateChain: true,
        validateHost: true
    )
]

let manager = Manager(
    configuration: URLSessionConfiguration.default,
    serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
)

let provider = MoyaProvider<MyTarget>(manager: manager)

plugins

最后您还可以向provider提供一个plugins数组。 这些接收在发送请求之前和接收到响应之后回调。 有一些插件已经包括:一个用于网络活动(NetworkActivityPlugin),一个用于记录所有网络活动(NetworkLoggerPlugin),另一个用于HTTP验证。
例如,您可以通过在Endpoint的plugins参数传递[NetworkLoggerPlugin()]来启用logger plugin。 注意,插件也可以是可配置的,例如已经包含的NetworkActivityPlugin需要一个networkActivityClosure参数。 可配置的插件实现如下所示:

ublic final class NetworkActivityPlugin: PluginType {

    public typealias NetworkActivityClosure = (change: NetworkActivityChangeType) -> ()
    let networkActivityClosure: NetworkActivityClosure

    public init(networkActivityClosure: NetworkActivityClosure) {
        self.networkActivityClosure = networkActivityClosure
    }

    // MARK: Plugin

    /// Called by the provider as soon as the request is about to start
    public func willSend(request: RequestType, target: TargetType) {
        networkActivityClosure(change: .began)
    }

    /// Called by the provider as soon as a response arrives
    public func didReceive(data: Data?, statusCode: Int?, response: URLResponse?, error: ErrorType?, target: TargetType) {
        networkActivityClosure(change: .ended)
    }
}

networkActivityClosure是一个闭包,您可以提供此闭包,以便在网络请求开始或结束时收到通知。 这对于使用网络活动指示器很有用。 注意这个闭包的签名是(change:NetworkActivityChangeType) - >(),因此只有当请求有.began或.end时才会通知您 - 您不会被提供请求本身的任何其他详细信息。

Plugins功能翻译

Moya插件用于修改请求和响应或执行副作用。 调用一个插件:

  • (prepare)在Moya已经将TargetType解析为URLRequest之后,这是在发送请求之前修改请求的机会(例如添加头)。
  • (willSend)在请求被发送前,这是检查请求并执行任何副作用(例如日志记录)的机会。
  • (didReceive)这是请求返回后,执行副作用的机会。
  • (process)在完成调用结果之前,这是对请求的结果进行任何修改的机会。

Built in plugins

Moya附带一些默认插件,可用于常用功能:身份验证,网络活动指示灯管理和日志记录。在provider初始化的时候你可以简单的声明一个插件:

let provider = MoyaProvider<GitHub>(plugins: [NetworkLoggerPlugin(verbose: true)])

Authentication

认证插件允许用户为每个请求分配一个可选的URLCredential。 收到请求时没有操作。
该插件可以在Sources/Moya/Plugins/CredentialsPlugin.swift找到

Network Activity Indicator

iOS网络的一个常见任务是在网络请求期间显示网络活动指示器,并在所有请求完成后将其删除。provided插件添加回调,在请求开始和结束时调用回调,可用于跟踪正在进行的请求数,并相应地显示/隐藏网络活动指示器。
该插件可以在Sources/Moya/Plugins/NetworkActivityPlugin.swift找到

Logging

在开发期间,将网络活动记录到控制台非常有用。 这可以是从发送和接收的请求的URL到记录完整头,方法,请求正文等任何东西。
provided的日志插件是最复杂的插件,并且可以配置为适合您的应用程序(和构建类型)所需的日志量。初始化插件时,您可以选择是否verbosity,是否记录curl命令以及提供输出数据的功能(如果您使用自己的日志框架代替print),并在打印之前格式化数据(默认情况下,返回数据将用String.Encoding.utf8转换为字符串,但如果你想转换为完美打印的JSON为你的响应,你可以传入一个formatter函数,请参阅Demo/Shared/GitHubAPI.swift中的函数JSONResponseDataFormatter的一个例子)
该插件可以在Sources/Moya/Plugins/NetworkLoggerPlugin.swift找到

Custom plugins

每次您需要在发送请求之前和/或响应后立即执行一些代码,您可以创建一个自定义插件,实现PluginType协议。 有关创建插件的示例,请参阅docs/Examples/CustomPlugin.md and docs/Examples/AuthPlugin.md.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容