最初の知り合い
実際、私はこのライブラリに何度か出くわし、ブラウザのタブにほこりが散らばっていましたが、勉強を延期しましたが、後で何度も後悔しました。 このライブラリの作成者は、「前」と「後」の雄弁な写真をリポジトリに投稿しました。
印象的でしょ? ライブラリの本質は、ネットワーク全体を最小限の動きで迅速に統合できることです。すべての低レベルの作業はMoyaによって行われます。
統合を開始
シングルビューアプリケーションを作成してライブラリをプロジェクトに接続しましょう(マッピングには、 ObjectMapperライブラリを使用し、サードパーティの依存関係を接続するには-CocoaPodsを使用します )
ポッドファイル
platform :ios, '9.0'
def app_pods
pod 'ObjectMapper', '~> 2.2'
pod 'Moya'
pod 'Moya-ObjectMapper'
end
target 'MoyaExample' do
use_frameworks!
app_pods
# Pods for MoyaExample
target 'MoyaExampleTests' do
inherit! :search_paths
app_pods
end
end
次に、リクエストを含むファイルを作成する必要があります。これは次のように行われます。
import Moya enum MoyaExampleService { case getRestaurants(page: Int?, perPage: Int?) } extension MoyaExampleService: TargetType { var baseURL: URL { return URL(string: "http://moya-example.svyatoslav-reshetnikov.ru")! } var path: String { switch self { case .getRestaurants: return "/restaurants.json" } var method: Moya.Method { return .get } var parameters: [String: Any]? { return nil } var parameterEncoding: ParameterEncoding { return URLEncoding.default } var sampleData: Data { return Data() } var task: Task { return .request } }
このファイルでは、リクエストが設定されています。 最初に列挙型が表示されます-これはすべてのリクエストを処理する将来のサービスです。 すべての要求を1つのサービスに詰め込むことができますが、大規模なプロジェクトでは、 SOLIDからの手紙Iに固執し、ファイルを混乱させないことをお勧めします。 すべてのリクエストを列挙にリストした後、
TargetType
プロトコルでクラスを拡張する必要があります。 このプロトコルの内容を詳しく見てみましょう。
1.
var baseURL
は、RESTful APIが存在するサーバーのアドレスです。
2.
var path
これらは要求ルートです。
3.
var method
は、送信するメソッドです。 モヤは何も発明せず、アラモファイアのすべての方法を取り入れています。
4.
var parameters
はクエリパラメーターです。 この段階では、ライブラリはこれらのパラメータがリクエスト本文(POST)にあるかURL(GET)にあるかを気にしません。これらのニュアンスは後で決定されます。 とりあえず、リクエストで渡したいパラメーターを書くだけです。
5.
var parameterEncoding
は、同じくAlamofireから取得したパラメーターエンコーディングです。 それらをjson、url、プロパティリストとして作成できます。
6.
var sampleData
これらは、テストに使用されるいわゆるスタブです。 サーバーから標準応答を取得し、JSON形式でプロジェクトに保存して、単体テストで使用できます。
7.
var task
は、実行するタスクです。 リクエスト、ダウンロード、アップロードの3つのみです。
私たちはプロジェクトに応募します
Moyaの使用を開始するには、プロバイダーを作成する必要があります-これは、リクエストへのアクセスを提供するライブラリーの抽象化です:
let provider = MoyaProvider<MoyaExampleService>()
その後、プロバイダーを使用してリクエストを行うこと
provider.request(.getRestaurants()) { result in switch result { case .success(let response): let restaurantsResponse = try? response.mapObject(RestaurantsResponse.self) // Do something with restaurantsResponse case .failure(let error): print(error.errorDescription ?? "Unknown error") } }
反応性を追加
MoyaはReactiveSwiftとRxSwiftをサポートしています。 個人的に、私は最新のライブラリを好むので、私の例は彼女のためです。 まず、必要な依存関係を追加しましょう。
ポッドファイル
プラットフォーム:ios、「9.0」
def app_pods
ポッド「ObjectMapper」、「〜> 2.2」
ポッド「モヤ」
ポッド「Moya-ObjectMapper」
ポッド「Moya / RxSwift」
ポッド「Moya-ObjectMapper / RxSwift」
終わり
ターゲット 'MoyaExample' do
use_frameworks!
app_pods
#MoyaExampleのポッド
ターゲット 'MoyaExampleTests' do
継承! :search_paths
app_pods
終わり
終わり
def app_pods
ポッド「ObjectMapper」、「〜> 2.2」
ポッド「モヤ」
ポッド「Moya-ObjectMapper」
ポッド「Moya / RxSwift」
ポッド「Moya-ObjectMapper / RxSwift」
終わり
ターゲット 'MoyaExample' do
use_frameworks!
app_pods
#MoyaExampleのポッド
ターゲット 'MoyaExampleTests' do
継承! :search_paths
app_pods
終わり
終わり
また、コードは次のように変換されます。
let provider = RxMoyaProvider<MoyaExampleService>() provider.request(.getRestaurants()) .mapObject(RestaurantsResponse.self) .catchError { error in // Do something with error return Observable.error(error) } .subscribe( onNext: { response in self.restaurants = response.data } ) .addDisposableTo(disposeBag)
モヤとのトリックのペア
Moyaのすべての機能について話すのは長いので、この記事を読んだ後、 ドキュメントをご覧になることをお勧めします。 そして今、私はあなたに役立つかもしれないいくつかのことを紹介します:
1.要求ヘッダーに何かを追加します(たとえば、基本認証)
まず、requestClosureを作成しましょう-これは、送信されたリクエストを変更できるクロージャーです。
let requestClosure = { (endpoint: Endpoint<MoyaExampleService>, done: MoyaProvider.RequestResultClosure) in var request = endpoint.urlRequest request?.setValue("set_your_token", forHTTPHeaderField: "XAuthToken") done(.success(request!)) }
このrequestClosureをプロバイダーに追加する必要があります。
let provider = RxMoyaProvider<MoyaExampleService>(requestClosure: requestClosure)
2.リクエストを転送する
Moyaにはクールなものがあります-プラグイン、詳細を調べることをお勧めします。 たとえば、プラグインの1つは、すべてのリクエストをコンソールに自動的に表示します。
let provider = RxMoyaProvider<MoyaExampleService>(plugins: [NetworkLoggerPlugin(verbose: true)])
単体テスト
私はBDDスタイルのテストを好むので、ユニットテストにはQuickおよびNimbleライブラリを使用します。 それらをPodfileに追加します。
ポッドファイル
プラットフォーム:ios、「9.0」
def app_pods
ポッド「ObjectMapper」、「〜> 2.2」
ポッド「モヤ」
ポッド「Moya-ObjectMapper」
ポッド「Moya / RxSwift」
ポッド「Moya-ObjectMapper / RxSwift」
終わり
def test_pods
ポッド「クイック」
ポッド「ニンブル」
終わり
ターゲット 'MoyaExample' do
use_frameworks!
app_pods
#MoyaExampleのポッド
ターゲット 'MoyaExampleTests' do
継承! :search_paths
app_pods
test_pods
終わり
終わり
def app_pods
ポッド「ObjectMapper」、「〜> 2.2」
ポッド「モヤ」
ポッド「Moya-ObjectMapper」
ポッド「Moya / RxSwift」
ポッド「Moya-ObjectMapper / RxSwift」
終わり
def test_pods
ポッド「クイック」
ポッド「ニンブル」
終わり
ターゲット 'MoyaExample' do
use_frameworks!
app_pods
#MoyaExampleのポッド
ターゲット 'MoyaExampleTests' do
継承! :search_paths
app_pods
test_pods
終わり
終わり
次に、小さなテストを作成します。
import Quick import Nimble import RxSwift import Moya @testable import MoyaExample class NetworkTests: QuickSpec { override func spec() { var testProvider: RxMoyaProvider<MoyaExampleService>! let disposeBag = DisposeBag() beforeSuite { testProvider = RxMoyaProvider<MoyaExampleService>(stubClosure: MoyaProvider.immediatelyStub) } describe("testProvider") { it("should be not nil") { expect(testProvider).toNot(beNil()) } } describe("getRestaurants") { it("should return not nil RestaurantsResponse object") { testProvider.request(.getRestaurants()) .mapObject(RestaurantsResponse.self) .subscribe( onNext: { response in expect(response).toNot(beNil()) } ) .addDisposableTo(disposeBag) } } } }
テストを実行し、合格したことを確認してから、ネットワーク部分がテストで100%カバーされていることを確認します(xcodeでコードカバレッジを有効にする方法については、 こちらをお読みください )。
おわりに
この記事では、強力なMoyaネットワークライブラリの基本的なアイデアを読者に提供し、意図的にニュアンスを下げて、独立して探索し、iOS開発でネットワークレイヤーを構築するときに幅広いタスクを解決できる開発ツールを楽しむことができるようにしました。 Githubでソースコードが待っています。