I'm trying to use the Google MLKitTranslate framework for offline translation in my app. I have written a function for downloading a language model.
public func downloadModel(forLanguage language: TranslateLanguage) -> Observable<Double> {
let model = TranslateRemoteModel.translateRemoteModel(language: language)
return Observable<Double>.create { _ -> Disposable in
// Observe the download progress
self.progress = ModelManager.modelManager().download(
model,
conditions: ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
)
return Disposables.create()
}
}
progress
here has the Progress
type.
However I want to create an Observable that sends out a .next event when I have an update in the .fractionComplete
and a .completed
event when .fractionComplete
is 1.0.
I have tried using .rx.observe
and .rx.observeWeakly
(KVO) on the progress object but it didn't work.
So how can I create an observable from this Progress event? Help is much appreciated.
This should work:
func downloadModel(forLanguage language: TranslateLanguage) -> Observable<Double> {
let model = TranslateRemoteModel.translateRemoteModel(language: language)
return Observable.create { observer -> Disposable in
let progress = ModelManager.modelManager().download(
model,
conditions: ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
)
return progress.rx.observe(Double.self, "fractionCompleted")
.compactMap { $0 }
.takeUntil(.inclusive, predicate: { $0 >= 1.0 })
.subscribe(observer)
}
}
A couple of things to note. This is not a method, do not put it in a class. It is a free function. The progress
object does not need to be retained by any class, the model manager will retain it and release it when it isn't needed anymore.
If you are using the create(_:)
operator, do not ignore the parameter being passed into your closure. If you do that you will not be able to emit anything.