Let's say I create an Observable for each image download
for _ in 0...N {
let s : Single<UIImage?> = fetchImage(from url)
}
How can I:
Thanks!
create a new Observable to emit an event when a download is completed
Look at the method imageObservable
for a possible implementation.
create a new Observable to emit only completed event when all download is completed
The zip
(documentation) operator might be what you are looking for.
import RxSwift
import UIKit
enum CustomError: Error {
case someError
}
class Executer {
let disposeBag = DisposeBag()
func execute() {
let imageURLs = [
URL(string: "http://via.placeholder.com/350x150")!,
URL(string: "http://via.placeholder.com/350x150")!
]
let imageObservables = imageURLs.map { self.imageObservable(url: $0) }
Observable
.zip(imageObservables) // wait for all image requests to finish
.subscribe(onNext: { images in
// here you have every single image in the 'images' array
images.forEach { print($0) }
})
.disposed(by: disposeBag)
}
// wrap 'URLSession' datatask into an observable
func imageObservable(url: URL) -> Observable<UIImage> {
return Observable.create { observer in
URLSession
.shared
.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
if let error = error {
observer.onError(error)
return
}
guard let data = data, let image = UIImage(data: data) else {
observer.onError(CustomError.someError)
return
}
observer.onNext(image)
observer.onCompleted()
})
.resume()
return Disposables.create()
}
}
}
This answer might also be relevant for you.