This gist is a sample to demonstrate the libraries Carlos, Moya, RxSwift working together.
Last active
January 4, 2019 03:35
-
-
Save pietrocaselani/9b992e00c7615227f8614567249429eb to your computer and use it in GitHub Desktop.
Carlos + Moya + Rx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func example() -> Single<String> { | |
let cache = MemoryCacheLevel() | |
.compose(DiskCacheLevel<GithubService, NSData>()) | |
.compose(MoyaFetcher(provider: provider)) | |
return cache.get(GithubService.zen) | |
.asObservable() | |
.map { data -> String in | |
guard let string = String(data: data as Data, encoding: .utf8) else { | |
throw MappingError.string(data) | |
} | |
return string | |
} | |
.asSingle() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PiedPiper | |
import RxSwift | |
extension Future { | |
func asObservable() -> Observable<T> { | |
let observable = Observable<T>.create { observer in | |
self.onCompletion { (result: Result<T>) in | |
switch result { | |
case .cancelled: | |
observer.onCompleted() | |
case .success(let value): | |
observer.onNext(value) | |
observer.onCompleted() | |
case .error(let error): | |
observer.onError(error) | |
} | |
} | |
return Disposables.create { | |
self.cancel() | |
} | |
} | |
return observable | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Carlos | |
import Moya | |
enum GithubService { | |
case zen | |
} | |
extension GithubService: TargetType, StringConvertible { | |
func toString() -> String { | |
return self.path | |
} | |
var baseURL: URL { | |
return URL(string: "https://api.github.com")! | |
} | |
var path: String { | |
switch self { | |
case .zen: | |
return "/zen" | |
} | |
} | |
var method: Moya.Method { | |
switch self { | |
case .zen: | |
return .get | |
} | |
} | |
var parameters: [String: Any]? { | |
switch self { | |
case .zen: | |
return nil | |
} | |
} | |
var parameterEncoding: ParameterEncoding { | |
switch self { | |
case .zen: | |
return URLEncoding.default | |
} | |
} | |
var task: Task { | |
switch self { | |
case .zen: | |
return .request | |
} | |
} | |
var headers: [String: String]? { | |
switch self { | |
case .zen: | |
return nil | |
} | |
} | |
var sampleData: Data { | |
return Data() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Carlos | |
import Moya | |
import PiedPiper | |
final class MoyaFetcher<Target:TargetType>: Fetcher { | |
typealias KeyType = Target | |
typealias OutputType = NSData | |
private let lock: ReadWriteLock = PThreadReadWriteLock() | |
private var pendingRequests: [Future<OutputType>] = [] | |
private let provider: MoyaProvider<Target> | |
init(provider: MoyaProvider<Target>) { | |
self.provider = provider | |
} | |
func get(_ key: Target) -> Future<OutputType> { | |
let promise = startRequest(target: key) | |
promise.onSuccess { _ in | |
self.removePendingRequests(promise) | |
}.onFailure { _ in | |
self.removePendingRequests(promise) | |
}.onCancel { | |
self.removePendingRequests(promise) | |
} | |
self.addPendingRequest(promise) | |
return promise.future | |
} | |
private func startRequest(target: Target) -> Future<OutputType> { | |
let promise = Promise<OutputType>() | |
let cancellable = provider.request(target) { result in | |
DispatchQueue.main.async { | |
if case .success(let data) = result { | |
promise.succeed(data.data as NSData) | |
} else if case .failure(let error) = result { | |
promise.fail(error) | |
} | |
} | |
} | |
promise.onCancel { | |
cancellable.cancel() | |
} | |
return promise.future | |
} | |
private func addPendingRequest(_ request: Future<OutputType>) { | |
lock.withWriteLock { | |
self.pendingRequests.append(request) | |
} | |
} | |
private func removePendingRequests(_ request: Future<OutputType>) { | |
if let idx = lock.withReadLock({ self.pendingRequests.index(where: { $0 === request }) }) { | |
_ = lock.withWriteLock { | |
self.pendingRequests.remove(at: idx) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment