Reaktive can be exported and used in Swift as usual, however there are few limitations.
Reaktive should be exported to Swift if you want to use it there. The following Gradle configuration can be used as a reference.
kotlin {
targets
.filterIsInstance<KotlinNativeTarget>()
.filter { it.konanTarget.family == Family.IOS }
.forEach { target ->
target.binaries {
framework {
// Some setup code here
export("com.badoo.reaktive:reaktive:<version>")
}
}
}
sourceSets {
named("commonMain") {
dependencies {
api("com.badoo.reaktive:reaktive:<version>")
}
}
}
}
Reaktive sources (Observable
, Single
, Maybe
and Completable
) are Kotlin interfaces with generic types.
Since generics for interfaces are not exported to Swift,
Reaktive provides wrapper classes.
You can wrap Reaktive sources using corresponding wrap()
extension functions:
Observable<T>.wrap(): ObservableWrapper<T>
BehaviorObservable<T>.wrap(): BehaviorObservableWrapper<T>
- can be also used for exposingBehaviorSubject
Single<T>.wrap(): SingleWrapper<T>
Maybe<T>.wrap(): MaybeWrapper<T>
Completable.wrap(): CompletableWrapper
Example:
class SharedDataSource {
fun load(): SingleWrapper<String> =
singleFromFunction {
// A long running operation
"A result"
}
.subscribeOn(ioScheduler)
.observeOn(mainScheduler)
.wrap()
}
class SharedViewModel {
private val _state = BehaviorSubject(State())
val state: BehaviorObservableWrapper<State> = _state.wrap()
}
Reaktive wrappers can be used in Swift as usual:
func foo() {
let ds = SharedDataSource()
let disposable = ds.load().subscribe { result in
// Handle the result
}
// At some point later
disposable.dispose()
}
There is no published Reaktive-RxSwift interop modules currently, please see #538 for some explanation. However feel free to copy-paste the following solution.
import RxSwift
import YourKotlinFramework
extension RxSwift.Observable where Element : AnyObject {
static func from(_ observable: ObservableWrapper<Element>) -> RxSwift.Observable<Element> {
return RxSwift.Observable<Element>.create { observer in
let disposable = observable.subscribe(
onError: { observer.onError(KotlinError($0)) },
onComplete: observer.onCompleted,
onNext: observer.onNext
)
return Disposables.create(with: disposable.dispose)
}
}
}
extension RxSwift.Single where Element : AnyObject {
static func from(_ single: SingleWrapper<Element>) -> RxSwift.Single<Element> {
return RxSwift.Single<Element>.create { observer in
let disposable = single.subscribe(
onError: { observer(.failure(KotlinError($0))) },
onSuccess: { observer(.success($0)) }
)
return Disposables.create(with: disposable.dispose)
}
}
}
extension RxSwift.Maybe where Element : AnyObject {
static func from(_ maybe: MaybeWrapper<Element>) -> RxSwift.Maybe<Element> {
return RxSwift.Maybe<Element>.create { observer in
let disposable = maybe.subscribe(
onError: { observer(.error(KotlinError($0))) },
onComplete: { observer(.completed) },
onSuccess: { observer(.success($0)) }
)
return Disposables.create(with: disposable.dispose)
}
}
}
extension RxSwift.Completable {
static func from(_ completable: CompletableWrapper) -> RxSwift.Completable {
return RxSwift.Completable.create { observer in
let disposable = completable.subscribe(
onError: { observer(.error(KotlinError($0))) },
onComplete: { observer(.completed) }
)
return Disposables.create(with: disposable.dispose)
}
}
}
struct KotlinError : Error {
let throwable: KotlinThrowable
init (_ throwable: KotlinThrowable) {
self.throwable = throwable
}
}