Par défaut, Swift utilise la classe URLSession pour le traitement des communications, mais Moya est une bibliothèque qui lui sert de wrapper.
Cela semble être une méthode standard sur le site de développement car elle peut être écrite facilement. Particulièrement pratique lorsqu'il est combiné avec RxSwift.
Pour le moment, il est préférable de connaître la classe URLSession dans une certaine mesure, donc les débutants doivent d'abord s'habituer à URLSession, puis passer à Moya et se rendre compte qu'elle peut être utilisée facilement.
Officiel Client API réalisé avec 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
//Gestion des erreurs, etc. que vous souhaitez faire en commun tout au long du projet
observer(.error(error))
})
}
}
func makeRequest<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
provider.rx
.request(MultiTarget(request))
.flatMap({ response -> Single<Response> in
//Vérification de l'en-tête de la réponse
return Single.just(try response.lookingAllHeaderFields())
})
.flatMap { response -> Single<Response> in
//Vérifier le code d'erreur
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 {
//Gestion des erreurs, etc. que vous souhaitez faire en commun tout au long du projet
observer(.error(error))
})
}
}
func makeRequestStub<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
stubProvider.rx
.request(MultiTarget(request))
.flatMap({ response -> Single<Response> in
//Vérification de l'en-tête de la réponse
return Single.just(try response.lookingAllHeaderFields())
})
.flatMap { response -> Single<Response> in
//Vérifier le code d'erreur
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)")!
}
}
shared
comme objet Singleton afin que MoyaProvider survivra tout au long de l'exécution du programme. ing.APIClient.swift
final class APIClient {
private init() {}
static let shared = APIClient()
--- MultiTarget
est utilisé pour que différents types de TargetType puissent être affectés à MoyaProvider. En conséquence, le côté utilisateur du client API peut éviter de passer le TargetType au MoyaProvider via les génériques et peut masquer l'existence du MoyaProvider du côté utilisateur.
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)Etc. sont également possibles
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
//Gestion des erreurs, etc. que vous souhaitez faire en commun tout au long du projet
observer(.error(error))
})
}
}
func makeRequest<G: ApiTargetType>(_ request: G) -> Single<G.Reponse> {
provider.rx
.request(MultiTarget(request))
.flatMap({ response -> Single<Response> in
//Vérification de l'en-tête de la réponse
return Single.just(try response.lookingAllHeaderFields())
})
.flatMap { response -> Single<Response> in
//Vérifier le code d'erreur
return Single.just(try response.successfulStatusCodesPolicy())
}
.map(G.Reponse.self, failsOnEmptyData: false)
}
S'il y a quelque chose qui est commun à l'ensemble du projet (généralement, l'URL de base, etc.), c'est une bonne idée de le sortir et de créer un protocole TargetType.
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"
}
Client API réalisé avec Swift4 + Moya + RxSwift + Codable Moya/Examples/Multi-Target/ViewController.swift
Recommended Posts