Skip to content

Instantly share code, notes, and snippets.

@redent
Created February 27, 2017 13:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save redent/0fd56a47d7dfa3308cdbbb77eaa79c3d to your computer and use it in GitHub Desktop.
Save redent/0fd56a47d7dfa3308cdbbb77eaa79c3d to your computer and use it in GitHub Desktop.
APIResult enum type to wrap errors and utility classes for RxSwift
import Foundation
enum APIResult<T> {
case success(T)
case error(Error)
}
extension APIResult {
var error: Error? {
switch self {
case .error(let error):
return error
default:
return nil
}
}
var result: T? {
switch self {
case .success(let result):
return result
default:
return nil
}
}
}
protocol APIResultType {
associatedtype Element
func asApiResult() -> APIResult<Element>
}
extension APIResult: APIResultType {
typealias Element = T
func asApiResult() -> APIResult<T> {
return self
}
}
import Foundation
import RxSwift
import RxCocoa
typealias ObservableResult<E> = Observable<APIResult<E>>
extension ObservableType where E: APIResultType {
func `do`(onSuccess: @escaping (E.Element) throws -> Void) -> Observable<E> {
return self.do(onNext: { result throws in
if let element = result.asApiResult().result {
try onSuccess(element)
}
})
}
func filterSuccess() -> Observable<E.Element> {
return flatMap { $0.asApiResult().result }
}
func filterError() -> Observable<Error> {
return flatMap { $0.asApiResult().error }
}
func mapSuccess<T>(_ transform: @escaping (E.Element) throws -> T) -> ObservableResult<T> {
return map(transform)
}
func map<T>(_ transform: @escaping (E.Element) throws -> T) -> ObservableResult<T> {
return map { result throws -> APIResult<T> in
switch result.asApiResult() {
case .success(let innerResult):
return try .success(transform(innerResult))
case .error(let error):
return .error(error)
}
}
}
func flatMap<T>(_ transform: @escaping (E.Element) throws -> Observable<T>) -> ObservableResult<T> {
return flatMap { result throws -> ObservableResult<T> in
switch result.asApiResult() {
case .success(let innerResult):
let transformed = try transform(innerResult)
return transformed.map { APIResult.success($0) }
case .error(let error):
return Observable.just(.error(error))
}
}
}
func splitSuccess() -> (success: Observable<E.Element>, error: Observable<Error>) {
let shared = shareReplayLatestWhileConnected()
return (shared.filterSuccess(), shared.filterError())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment