Created
February 27, 2017 13:09
-
-
Save redent/0fd56a47d7dfa3308cdbbb77eaa79c3d to your computer and use it in GitHub Desktop.
APIResult enum type to wrap errors and utility classes for RxSwift
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 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 | |
} | |
} |
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 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