Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Last active March 20, 2019 20:24
Show Gist options
  • Save IanKeen/04393f2f29d9c3e67025d96589fdfb97 to your computer and use it in GitHub Desktop.
Save IanKeen/04393f2f29d9c3e67025d96589fdfb97 to your computer and use it in GitHub Desktop.
RxSwift subject to provide public triggering but private subscription
extension Driver {
/// Create separate input/output access to the same underlying subject
///
/// This allows the subject to be hidden and enforce singular access to input/output
/// as well as only exposing input _or_ output if needed.
///
/// - Parameters:
/// - default: The default value to emit in the case of any errors
/// - value: The value to start with
public static func create(withDefault default: E? = nil, startingWith value: E) -> (input: AnyObserver<E>, output: Driver<E>) {
let (input, output) = create(withDefault: `default`)
return (input, output.startWith(value))
}
/// Create separate input/output access to the same underlying subject
///
/// This allows the subject to be hidden and enforce singular access to input/output
/// as well as only exposing input _or_ output if needed.
///
/// - Parameter default: The default value to emit in the case of any errors
public static func create(withDefault default: E? = nil) -> (input: AnyObserver<E>, output: Driver<E>) {
let instance = PublishSubject<E>()
return (
AnyObserver(instance),
instance.asDriver(onErrorDriveWith: `default`.map(Driver.just) ?? .never())
)
}
}
class API {
func obtainIds() -> Observable<[Int]> {
return .just([1,2,3,4])
}
}
class ViewModel {
let update: AnyObserver<Void>
let dataUpdated: Driver<[String]>
init(api: API) {
//
// here is where we create the input/output
let update = Driver<Void>.create()
//
//
self.update = update.input
self.dataUpdated = update.output
.flatMap {
return api
.obtainIds()
.asDriver(onErrorJustReturn: [])
}
.map { $0.flatMap(String.init) }
}
}
// in your view controllers data binding..
let viewModel = ViewModel(api: API())
// perhaps bind to a tableview
viewModel.dataUpdated.drive { e in
print(e)
}
// button triggers the input
someButton.rx.tap.bind(to: viewModel.update)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment