Ein Beispiel für einen Moya + RxSwift-API-Client (Swift5)

Annahme

Standardmäßig verwendet Swift die URLSession-Klasse für die Kommunikationsverarbeitung, aber Moya ist eine Bibliothek, die als Wrapper dafür dient.

Da es bequem geschrieben werden kann, scheint es eine Standardmethode am Entwicklungsstandort zu sein. Besonders praktisch in Kombination mit RxSwift.

Derzeit ist es besser, die URLSession-Klasse bis zu einem gewissen Grad zu kennen. Anfänger sollten sich daher zunächst an URLSession gewöhnen und dann zu Moya wechseln, um zu erkennen, dass sie bequem verwendet werden kann.

Offiziell API-Client erstellt mit Swift4 + Moya + RxSwift + Codable

Das ganze

APIClient.swift

APIClient.swift


final class APIClient {
    private init() {}
    static let shared = APIClient()

    // MARK: - Private

    private let provider = MoyaProvider<MultiTarget>()

    private let stubProvider = MoyaProvider<MultiTarget>(stubClosure: MoyaProvider.immediatelyStub)

    // MARK: - Public

    func request<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        Single<G.Reponse>.create { observer in
            self.makeRequest(request)
                .subscribe(onSuccess: { response in
                    observer(.success(response))
                }, onError: { error in
                    //Fehlerbehandlung usw., die Sie im gesamten Projekt gemeinsam ausführen möchten
                    observer(.error(error))
                })
        }
    }

    func makeRequest<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        provider.rx
            .request(MultiTarget(request))
            .flatMap({ response -> Single<Response> in
                //Überprüfen des Antwortheaders
                return Single.just(try response.lookingAllHeaderFields())
            })
            .flatMap { response -> Single<Response> in
                //Überprüfen Sie den Fehlercode
                return Single.just(try response.successfulStatusCodesPolicy())
        }
        .map(G.Reponse.self, failsOnEmptyData: false)
    }

    func requestStub<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        Single<G.Reponse>.create { observer in
            self.makeRequestStub(request)
                .subscribe(onSuccess: { response in
                    observer(.success(response))
                }, onError: { error in
                    if let error = error as? MoyaError {
                    //Fehlerbehandlung usw., die Sie im gesamten Projekt gemeinsam ausführen möchten
                    observer(.error(error))
                })
        }
    }

    func makeRequestStub<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        stubProvider.rx
            .request(MultiTarget(request))
            .flatMap({ response -> Single<Response> in
                //Überprüfen des Antwortheaders
                return Single.just(try response.lookingAllHeaderFields())
            })
            .flatMap { response -> Single<Response> in
                //Überprüfen Sie den Fehlercode
                return Single.just(try response.successfulStatusCodesPolicy())
        }
        .map(G.Reponse.self, failsOnEmptyData: false)
    }
}

ApiTargetType.swift

ApiTargetType.swift


import Foundation
import Moya

protocol ApiTargetType: TargetType {
    associatedtype Response: Codable
}

extension ApiTargetType {

    /// The target's base `URL`.
    var baseURL: URL {
        URL(string: "\(URLs.baseURL)")!
    }
}

Kommentar

Der API-Client ist ein Singleton-Objekt

APIClient.swift


final class APIClient {
    private init() {}
    static let shared = APIClient()
MultiTarget verwenden

--- MultiTarget wird verwendet, damit MoyaProvider verschiedene Arten von TargetType zugewiesen werden können. Infolgedessen kann die API-Client-Benutzerseite die Mühe ersparen, den TargetType über die Generika an den MoyaProvider zu übergeben, und die Existenz des MoyaProvider vor der Benutzerseite verbergen.

APIClient.swift


private let provider = MoyaProvider<MultiTarget>()
Verwendung des Plugins

APIClient.swift


private let provider = MoyaProvider<MultiTarget>(plugins: [FooPlugin()])

Plugin.swift


/// A Moya Plugin receives callbacks to perform side effects wherever a request is sent or received.
///
/// for example, a plugin may be used to
///     - log network requests
///     - hide and show a network activity indicator
///     - inject additional information into a request
public protocol PluginType {
    /// Called to modify a request before sending.
    func prepare(_ request: URLRequest, target: TargetType) -> URLRequest

    /// Called immediately before a request is sent over the network (or stubbed).
    func willSend(_ request: RequestType, target: TargetType)

    /// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.
    func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType)

    /// Called to modify a result before completion.
    func process(_ result: Result<Moya.Response, MoyaError>, target: TargetType) -> Result<Moya.Response, MoyaError>
}
Verwendung von stubProvider

APIClient.swift


    private let stubbingProvider = MoyaProvider<MultiTarget>(stubClosure: MoyaProvider.immediatelyStub) //.delayed(seconds: 1.0)Usw. sind ebenfalls möglich
Überprüfen der Antwort

APIClient.swift


    // MARK: - Public

    func request<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        Single<G.Reponse>.create { observer in
            self.makeRequest(request)
                .subscribe(onSuccess: { response in
                    observer(.success(response))
                }, onError: { error in
                    //Fehlerbehandlung usw., die Sie im gesamten Projekt gemeinsam ausführen möchten
                    observer(.error(error))
                })
        }
    }

    func makeRequest<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
        provider.rx
            .request(MultiTarget(request))
            .flatMap({ response -> Single<Response> in
                //Überprüfen des Antwortheaders
                return Single.just(try response.lookingAllHeaderFields())
            })
            .flatMap { response -> Single<Response> in
                //Überprüfen Sie den Fehlercode
                return Single.just(try response.successfulStatusCodesPolicy())
        }
        .map(G.Reponse.self, failsOnEmptyData: false)
    }

Zieltyp

Wenn das gesamte Projekt etwas gemeinsam hat (normalerweise die Basis-URL usw.), empfiehlt es sich, es zu löschen und ein TargetType-Protokoll zu erstellen.

python


protocol ApiTargetType: TargetType {
    associatedtype Response: Codable
}

extension ApiTargetType {

    /// The target's base `URL`.
    var baseURL: URL {
        URL(string: "\(URLs.baseURL)")!
    }
}

Anwendungsbeispiel

python


    func fetchData() -> Single<HogeEntity> {
        return APIClient.shared.request(HogeTargetType())
    }

HogeTargetType.swift


import Foundation
import Moya

struct HogeTargetType: ApiTargetType {
    typealias Response = HogeEntity

    var path: String {
        return "/hogehoge/"
    }

    var method: Moya.Method {
        return .get
    }
    var task: Task {
        let param: [String: Any] = [
            "id": id
        ]

        return .requestParameters(parameters: param, encoding: URLEncoding.default)
    }
    var headers: [String: String]? {
        [
            "Content-Type": "application/json",
            "x-auth-token": API.authToken
        ]
    }

       var sampleData: Data {
        let path = Bundle.main.path(forResource: "Hoge", ofType: "json")!
        guard let file = FileHandle(forReadingAtPath: path) else {
            return Data()
        }

        return file.readDataToEndOfFile()
    }

    // MARK: - Arguments

    /// ID
    var id: String {
        return DataManager.shared.id ?? ""
    }

    init() {}
}

HogeEntity.swift


struct HogeEntity: Codable {
   let fuga: String

Hoge.json


{
   "fuga": "test"
}

Referenzmaterial

API-Client erstellt mit Swift4 + Moya + RxSwift + Codable Moya/Examples/Multi-Target/ViewController.swift

Recommended Posts

Ein Beispiel für einen Moya + RxSwift-API-Client (Swift5)
[swift5] Versuchen Sie, einen API-Client auf verschiedene Arten zu erstellen
Verwenden Sie Swift, um eine Annäherung an sinx zu finden
Finden Sie mit Swift eine Annäherung an cosx
Ein einfaches Beispiel für das MVC-Modell
Ich habe einen API-Client für Nature Remo erstellt