原文地址: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 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 in
let defaultEndpoint = MoyaProvider.defaultEndpointMapping(target)
return defaultEndpoint.adding(newHttpHeaderFields: ["APP_NAME": "MY_AWESOME_APP"])
}
let provider = MoyaProvider(endpointClosure: endpointClosure)
这也意味着您可以向部分或所有endPoint提供额外参数。 例如,假设我们需要假设的MyTarget目标的所有值的认证令牌,除了实际进行认证的目标之外。 我们可以构造类似于以下的endpointClosure。
let endpointClosure = { (target: MyTarget) -> Endpoint 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(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
let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
var request = endpoint.urlRequest
// Modify the request however you like.
done(.success(request))
}
let provider = MoyaProvider(requestClosure: requestClosure)
此requestClosure可用于修改特定于URLRequest的属性或向请求提供直到该请求创建成功才能知道的信息,例如Cookie设置。注意上面提到的endpointClosure不是用于这个目的或任何特定于请求的应用程序级映射。
此参数实际上对修改请求对象非常有用。 URLRequest有很多可以自定义的属性。假设您要停用所有要求的Cookie:
{ (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
var request: URLRequest = endpoint.urlRequest
request.httpShouldHandleCookies = false
done(.success(request))
}
您还可以执行网络请求的日志记录,因为此闭包在请求发送到网络之前被调用。
Providers功能翻译
当使用Moya时,您通过MoyaProvider实例创建所有API请求,传递一个枚举值,指定您要调用的endpoint。 设置好您的endpoint后,您基本上设置好了基本用法:
let provider = MoyaProvider()
经过简单的设置,你就可以开始请求了:
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 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(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(stubClosure: { (_: MyTarget) -> Moya.StubBehavior in return .immediate })
let provider = MoyaProvider(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(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(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.