原文地址:https://github.com/Moya/Moya/tree/master/docs
參考文章:http://www.itdecent.cn/p/c1494681400b
Endpoints功能翻譯
endpoint是Moya用來推斷最終將要進行的網(wǎng)絡請求的半內(nèi)部數(shù)據(jù)結(jié)構(gòu)。 endpoint存儲以下數(shù)據(jù):
- The url.
- The HTTP method (GET, POST, etc).
- The request parameters.
- The parameter encoding (URL, JSON, custom, etc). 參數(shù)編碼
- The HTTP request header fields. 請求頭
- The sample response (for unit testing). 測試數(shù)據(jù)返回
Providers將Targets的數(shù)據(jù)解析Endpoint里面,再將Endpoint解析到實際的網(wǎng)絡請求中.
這里有兩種方式和Endpoint交互
1.當創(chuàng)建provider時,可以指定從Target到Endpoint的映射方式。
2.當創(chuàng)建provider時,可以指定從Endpoint到URLRequest的映射方式。
第一條類似于以下內(nèi)容
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提供的默認實現(xiàn)。 如果您需要某些自定義內(nèi)容,例如,如果您的API需要自定義參數(shù)解析,或者如果您要創(chuàng)建一個在單元測試中返回非200 HTTP狀態(tài)的測試提供程序,這就是你可以修改的地方。
第二種使用是非常罕見的。 Moya試圖阻止你不必擔心低級細節(jié)。如果你需要它也可以進行修改。 其使用在下面進一步描述。
讓我們來看一個提供從Target到Endpoint靈活解析的示例。
從Target 到 Endpoint
默認情況下,Endpoint實例使用URLEncoding.default類型參數(shù)編碼。 您可以在設置提供程序時使用endpointClosure中的Endpoint初始值設置的可選parameterEncoding參數(shù)指定在endpointClosure中逐個目標地編碼參數(shù)的方式。
有三種參數(shù)編碼類型:URL編碼,JSON編碼,PropertyList編碼,它直接映射到Alamofire中的相應類型.每個類型都有.default屬性,它給你一個特定的ParameterEncoding類型的默認實例。此外,如果你想創(chuàng)建你的自定義類型,只是實現(xiàn)ParameterEncoding協(xié)議就可以了.通常你只是想要URLEncoding.default,但你可以使用你喜歡的。這些直接映射到Alamofire參數(shù)編碼。 如果你想獲得關于ParameterEncoding類型的更多信息以及如何創(chuàng)建自己的,請查看Alamofire的關于這個問題的文檔。
您可以在此閉包中添加參數(shù)或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提供額外參數(shù)。 例如,假設我們需要假設的MyTarget目標的所有值的認證令牌,除了實際進行認證的目標之外。 我們可以構(gòu)造類似于以下的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的現(xiàn)有行為并擴展 - 而不是替換它。 add(newParameters :)和add(newHttpHeaderFields :)函數(shù)允許您依賴現(xiàn)有的Moya代碼并添加您自己的自定義值。
示例響應是TargetType協(xié)議的要求。 但是它們只指定返回的數(shù)據(jù)。 目標到端點映射閉包是可以指定更多細節(jié)的地方,這對單元測試很有用。
示例響應具有以下兩個值之一:
- NetworkError,帶有NSError?可選錯誤類型。
- NetworkResponse,具有Int狀態(tài)代碼和Data返回的數(shù)據(jù)。
Request Mapping
正如我們前面提到的,這個庫的目的不是真正提供一個編碼框架來訪問網(wǎng)絡 - 這是Alamofire的工作.相反,Moya是一種方式來構(gòu)思你對網(wǎng)絡訪問的想法,并提供編譯時檢查明確定義的網(wǎng)絡目標。您已經(jīng)了解了如何使用MoyaProvider初始值設定器的endpointClosure參數(shù)將Targets映射到endpoints。這讓你創(chuàng)建一個Endpoint實例,Moya將使用它來推斷網(wǎng)絡API調(diào)用。在某些時候,該Endpoints必須解析成一個實際的URLRequest給Alamofire。這就是requestClosure參數(shù)的用途。
requestClosure是一種可選的,用來修改網(wǎng)絡的請求的最后方式。它具有默認值MoyaProvider.DefaultRequestMapper,它只使用Endpoint實例的urlRequest屬性。
此閉包接收Endpoint實例,并負責調(diào)用RequestResultClosure(Result <URLRequest,MoyaError> - > Void的簡寫)的參數(shù)與表示Endpoint的請求。在這里做你的OAuth簽名或其他事情。因為你可以異步地調(diào)用閉包,你可以使用你喜歡的任何認證庫(例子)。除了修改請求,你可以簡單地記錄它。
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的屬性或向請求提供直到該請求創(chuàng)建成功才能知道的信息,例如Cookie設置。注意上面提到的endpointClosure不是用于這個目的或任何特定于請求的應用程序級映射。
此參數(shù)實際上對修改請求對象非常有用。 URLRequest有很多可以自定義的屬性。假設您要停用所有要求的Cookie:
{ (endpoint: Endpoint<ArtsyAPI>, done: MoyaProvider.RequestResultClosure) in
var request: URLRequest = endpoint.urlRequest
request.httpShouldHandleCookies = false
done(.success(request))
}
您還可以執(zhí)行網(wǎng)絡請求的日志記錄,因為此閉包在請求發(fā)送到網(wǎng)絡之前被調(diào)用。
Providers功能翻譯
當使用Moya時,您通過MoyaProvider實例創(chuàng)建所有API請求,傳遞一個枚舉值,指定您要調(diào)用的endpoint。 設置好您的endpoint后,您基本上設置好了基本用法:
let provider = MoyaProvider<MyService>()
經(jīng)過簡單的設置,你就可以開始請求了:
provider.request(.zen) { result in
// `result` is either .success(response) or .failure(error)
}
這就是全部的了! request()方法返回一個Cancellable,它只有一個公共函數(shù)cancel(),您可以使用它來取消請求。 有關Result類型的更多信息請參閱示例。
記住如何放置target和provider完全取決于你。 你可以查看Artsy的實現(xiàn)的例子。
但不要忘記在屬性中保留它的引用。 如果它被釋放,你會看到-999“cancelled”錯誤響應。
Advanced Usage
為了解釋MoyaProvider的所有配置選項,我們將在下面的章節(jié)逐一介紹每個參數(shù)。
endpointClosure:
MoyaProvider初始化程序的第一個(可選)參數(shù)是一個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就像你可以得到的一樣簡單。 它實際上也是默認實現(xiàn),存儲在MoyaProvider.defaultEndpointMapping。 查看Endpoints文檔了解更多有關為什么你需要自定義這些的信息。
requestClosure:
下一個可選的初始化參數(shù)是requestClosure,它將Endpoint解析為實際的URLRequest。 再次查看Endpoints文檔了解如何以及為什么這樣做。
stubClosure:
下一個選項是提供一個stubClosure。 這將返回.never(默認值),.immediate或.delayed(seconds)之一,您可以將已存根的請求延遲一定的時間。 例如,.delayed(0.2)將延遲每個存根請求。 這可以很好地模擬單元測試中的網(wǎng)絡延遲。
很好的是如果你需要不同于其他請求來存根一些請求,你可以使用自己的閉包。
let provider = MoyaProvider<MyTarget>(stubClosure: { target: MyTarget -> Moya.StubBehavior in
switch target {
/* Return something different based on the target. */
}
})
但通常你想要對所有的目標執(zhí)行同樣的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參數(shù)。 默認情況下,你會得到一個基本配置的自定義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
}
只有一個特別的事情:因為構(gòu)造一個Alamofire.Request在AF將默認立即激活請求,即使單元測試的stubbing請求。 因此在Moya中,startRequestsImmediately默認設置為false。
如果您想要自定義自己的管理器,例如要添加SSL綁定,請創(chuàng)建一個并傳遞進來,所有請求將路由通過自定義配置的管理器。
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數(shù)組。 這些接收在發(fā)送請求之前和接收到響應之后回調(diào)。 有一些插件已經(jīng)包括:一個用于網(wǎng)絡活動(NetworkActivityPlugin),一個用于記錄所有網(wǎng)絡活動(NetworkLoggerPlugin),另一個用于HTTP驗證。
例如,您可以通過在Endpoint的plugins參數(shù)傳遞[NetworkLoggerPlugin()]來啟用logger plugin。 注意,插件也可以是可配置的,例如已經(jīng)包含的NetworkActivityPlugin需要一個networkActivityClosure參數(shù)。 可配置的插件實現(xiàn)如下所示:
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是一個閉包,您可以提供此閉包,以便在網(wǎng)絡請求開始或結(jié)束時收到通知。 這對于使用網(wǎng)絡活動指示器很有用。 注意這個閉包的簽名是(change:NetworkActivityChangeType) - >(),因此只有當請求有.began或.end時才會通知您 - 您不會被提供請求本身的任何其他詳細信息。
Plugins功能翻譯
Moya插件用于修改請求和響應或執(zhí)行副作用。 調(diào)用一個插件:
- (prepare)在Moya已經(jīng)將TargetType解析為URLRequest之后,這是在發(fā)送請求之前修改請求的機會(例如添加頭)。
- (willSend)在請求被發(fā)送前,這是檢查請求并執(zhí)行任何副作用(例如日志記錄)的機會。
- (didReceive)這是請求返回后,執(zhí)行副作用的機會。
- (process)在完成調(diào)用結(jié)果之前,這是對請求的結(jié)果進行任何修改的機會。
Built in plugins
Moya附帶一些默認插件,可用于常用功能:身份驗證,網(wǎng)絡活動指示燈管理和日志記錄。在provider初始化的時候你可以簡單的聲明一個插件:
let provider = MoyaProvider<GitHub>(plugins: [NetworkLoggerPlugin(verbose: true)])
Authentication
認證插件允許用戶為每個請求分配一個可選的URLCredential。 收到請求時沒有操作。
該插件可以在Sources/Moya/Plugins/CredentialsPlugin.swift找到
Network Activity Indicator
iOS網(wǎng)絡的一個常見任務是在網(wǎng)絡請求期間顯示網(wǎng)絡活動指示器,并在所有請求完成后將其刪除。provided插件添加回調(diào),在請求開始和結(jié)束時調(diào)用回調(diào),可用于跟蹤正在進行的請求數(shù),并相應地顯示/隱藏網(wǎng)絡活動指示器。
該插件可以在Sources/Moya/Plugins/NetworkActivityPlugin.swift找到
Logging
在開發(fā)期間,將網(wǎng)絡活動記錄到控制臺非常有用。 這可以是從發(fā)送和接收的請求的URL到記錄完整頭,方法,請求正文等任何東西。
provided的日志插件是最復雜的插件,并且可以配置為適合您的應用程序(和構(gòu)建類型)所需的日志量。初始化插件時,您可以選擇是否verbosity,是否記錄curl命令以及提供輸出數(shù)據(jù)的功能(如果您使用自己的日志框架代替print),并在打印之前格式化數(shù)據(jù)(默認情況下,返回數(shù)據(jù)將用String.Encoding.utf8轉(zhuǎn)換為字符串,但如果你想轉(zhuǎn)換為完美打印的JSON為你的響應,你可以傳入一個formatter函數(shù),請參閱Demo/Shared/GitHubAPI.swift中的函數(shù)JSONResponseDataFormatter的一個例子)
該插件可以在Sources/Moya/Plugins/NetworkLoggerPlugin.swift找到
Custom plugins
每次您需要在發(fā)送請求之前和/或響應后立即執(zhí)行一些代碼,您可以創(chuàng)建一個自定義插件,實現(xiàn)PluginType協(xié)議。 有關創(chuàng)建插件的示例,請參閱docs/Examples/CustomPlugin.md and docs/Examples/AuthPlugin.md.