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
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)")!
}
}
APIClient.swift
final class APIClient {
private init() {}
static let shared = APIClient()
--- 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>()
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>
}
APIClient.swift
private let stubbingProvider = MoyaProvider<MultiTarget>(stubClosure: MoyaProvider.immediatelyStub) //.delayed(seconds: 1.0)Usw. sind ebenfalls möglich
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)
}
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)")!
}
}
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"
}
API-Client erstellt mit Swift4 + Moya + RxSwift + Codable Moya/Examples/Multi-Target/ViewController.swift
Recommended Posts