モヤ-ネットワークの部分について心配するのをやめて、生活を始める方法

こんにちは! プロジェクトを次のRESTful APIと統合する必要があるときの悲観を知っていますか? これは、ある種のAPIManagerを作成し、Alamofireクエリで埋めてからデータマッピングモデルに関連付ける必要がある場合です。 個人的には、すべての作業を可能な限り最適化するようにしています。そのため、繰り返しコードを大量に書いてルーチンを削除しないように、さまざまなライブラリを定期的に研究しています。 これらの訪問の1つで、素晴らしいMoyaライブラリに出会いました。



最初の知り合い



実際、私はこのライブラリに何度か出くわし、ブラウザのタブにほこりが散らばっていましたが、勉強を延期しましたが、後で何度も後悔しました。 このライブラリの作成者は、「前」と「後」の雄弁な写真をリポジトリに投稿しました。

画像

印象的でしょ? ライブラリの本質は、ネットワーク全体を最小限の動きで迅速に統合できることです。すべての低レベルの作業は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

終わり



終わり



また、コードは次のように変換されます。



 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

終わり



終わり



次に、小さなテストを作成します。



 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でソースコードが待っています。



All Articles