Итак, у меня есть базовый класс, от которого мои классы обслуживания могут наследовать для выполнения запросов. Ниже приведен фрагмент кода.
import Foundation
import Moya
import RxSwift
class BaseServiceRespository<Target: TargetType> {
private let disposeBag = DisposeBag()
private var provider: MoyaProvider<Target>!
init(_ provider: MoyaProvider<Target>!) {
self.provider = provider
}
func execute<T: Codable>(target: Target,
mapTo type: T.Type,
mapping: CodableMappingStrategy?) -> Observable<ServiceRespositoryResult<T>> {
return Observable.create { observer in
self.provider
.rx
.request(target)
.baseObservable()
.filterSuccessfulStatusCodes()
.subscribe(onNext: { response in
guard let mapping = mapping else {
observer.onNext(.success(ResponseObject(response: response, data: try? response.map(T.self))))
return
}
guard let decodedObj = try? response.map(T.self, atKeyPath: mapping.keypath, using: mapping.decoder, failsOnEmptyData: mapping.failsOnEmpty) else {
observer.onNext(.success(ResponseObject(response: response, data: nil)))
return
}
observer.onNext(.success(ResponseObject(response: response, data: decodedObj)))
}, onError: { error in
observer.onNext(.failure(error))
}).disposed(by: self.disposeBag)
return Disposables.create()
}
}
func executeArr<T: Codable>(target: Target,
mapTo type: T.Type,
mapping: CodableMappingStrategy?) -> Observable<ServiceRespositoryResultArray<T>> {
return Observable.create { observer in
self.provider
.rx
.request(target)
.baseObservable()
.filterSuccessfulStatusCodes()
.subscribe(onNext: { response in
guard let mapping = mapping else {
observer.onNext(.success(ResponseObject(response: response, data: try? response.map(Array<T>.self))))
return
}
guard let decodedObj = try? response.map(Array<T>.self, atKeyPath: mapping.keypath, using: mapping.decoder, failsOnEmptyData: mapping.failsOnEmpty) else {
observer.onNext(.success(ResponseObject(response: response, data: nil)))
return
}
observer.onNext(.success(ResponseObject(response: response, data: decodedObj)))
}, onError: { error in
observer.onNext(.failure(error))
}).disposed(by: self.disposeBag)
return Disposables.create()
}
}
}
Так что, если я хочу использовать этот класс для своего сервиса, все, что мне нужно сделать, это сделать его подклассом внутри своего класса обслуживания, как, например, и затем подписаться на фактический запрос через наблюдаемый в rx. Как и ниже.
import Foundation
import RxSwift
class LoginService: BaseServiceRespository<AccountEndPoint> {
private let disposeBag = DisposeBag()
func login(_ credentials: LoginCredentials) {
self.execute(target: .login(config: networkConfig, credentials: credentials), mapTo: String.self, mapping: CodableMappingBuilder().add(failOnEmpty: false).build())
.subscribe(onNext: { res in
switch res {
case .success(let response):
print(response.data)
case .failure(let error):
print(error)
}
}).disposed(by: disposeBag)
}
}
Итак, чтобы проверить, работает ли это, я просто пытаюсь выполнить этот код в viewDidLoad
LoginService.init(ServiceProviderBuilder<AccountEndPoint>().debug(verbose: true, cURL: true).build())
.login(LoginCredentials(emailAddress: "xxxxx", password: "xxxxx"))
Проблема, с которой я столкнулся, заключается в том, что моя, кажется, запускает запрос, но затем отменяет его, и я не слишком уверен, почему. Все, что я получаю от консоли, это следующее (я показываю только информацию с консоли, которая мне тоже разрешена ...). Но я ни в коем случае не отменяю запрос, и это меня немного смущает.
1> load failed with error Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=xxxxx, NSErrorFailingURLKey=xxxxx, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <91E9466B-7410-4E01-8FF4-CC314FC81BC5>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <91E9466B-7410-4E01-8FF4-CC314FC81BC5>.<1>, NSLocalizedDescription=cancelled} [-999]