2

I have a newBid object, that contains some data and images array. I want to upload all images and data to the server and zip those upload observables. If I create separate drivers for data, image1 and image2, I succeed.

But what I want to really do is to not hardcode images since array may contain from 0 to 10 images. I want to create observables array programmatically and zip them.

let dataSaved = saveTaps.withLatestFrom(newBid)
    .flatMapLatest { bid in
        return CustomerManager.shared.bidCreate(bid: bid)
            .trackActivity(activityIndicator)
            .asDriver(onErrorJustReturn: false)
}

let photoSaved0 = saveTaps.withLatestFrom(newBid)
    .flatMapLatest { bid in
        return CustomerManager.shared.bidUploadFile(image: bid.images[0])
            .trackActivity(activityIndicator)
            .asDriver(onErrorJustReturn: false)
}

let photoSaved1 = saveTaps.withLatestFrom(newBid)
    .flatMapLatest { bid in
        return CustomerManager.shared.bidUploadFile(image: bid.images[1])
            .trackActivity(activityIndicator)
            .asDriver(onErrorJustReturn: false)
}

saveCompleted = Driver.zip(dataSaved, photoSaved0, photoSaved1){ return $0 && $1 && $2 }

/*
// 0. Getting array of images from newBid
let images = newBid.map { bid in
    return bid.images
}

// 1. Creating array of upload drivers from array of images
let imageUploads = images.map { (images: [UIImage]) -> [Driver<Bool>] in
    var temp = [Driver<Bool>]()
    return temp
}

// 2. Zipping array of upload drivers to photoSaved driver
photoSaved = Driver
    .zip(imageUploads) // wait for all image requests to finish
    .subscribe(onNext: { results in
        // here you have every single image in the 'images' array
        results.forEach { print($0) }
    })
    .disposed(by: disposeBag)*/

In the commented section if I try to zip imageUploads, I get error:

Argument type 'SharedSequence<DriverSharingStrategy, [SharedSequence<DriverSharingStrategy, Bool>]>' does not conform to expected type 'Collection'

2 Answers 2

2

How about something like this?

let saves = saveTaps.withLatestFrom(newBid)
    .flatMapLatest { (bid: Bid) -> Observable<[Bool]> in
        let dataSaved = CustomerManager.shared.bidCreate(bid: bid)
            .catchErrorJustReturn(false)

        let photosSaved = bid.images.map {
            CustomerManager.shared.bidUploadFile(image: $0, bidID: bid.id)
                .catchErrorJustReturn(false)
        }

        return Observable.zip([dataSaved] + photosSaved)
            .trackActivity(activityIndicator)
    }
    .asDriver(onErrorJustReturn: []) // remove this line if you want an Observable<[Bool]>.
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, I will try.
As an FYI. The zip operator doesn't upload the images one at a time. It will start all the uploads at the same time and report back when they are all complete.
I have an error with this: Cannot convert value of type '(Bid) -> Observable<[Bool]>' to expected argument type '() -> SharedSequence<, _>'
What do your CustomerManager functions return? I was assuming they returned Observable<Bool>.
Yes. It returns Observable<Bool>
|
0

Final solution

let bidID: Driver<Int> = saveTaps.withLatestFrom(newBid)
    .flatMapLatest { bid in
        return CustomerManager.shared.bidCreate(bid: bid)
            .trackActivity(activityIndicator)
            .asDriver(onErrorJustReturn: 0)
}

saveCompleted = Driver.combineLatest(bidID, newBid) { bidID, newBid in
    newBid.uploadedImages.map {
        CustomerManager.shared.bidUploadFile(image: $0, bidID: bidID).asDriver(onErrorJustReturn: false)
    }
    }.flatMap { imageUploads in
        return Driver.zip(imageUploads).trackActivity(activityIndicator).asDriver(onErrorJustReturn: [])
    }.map{ (results:[Bool]) -> Bool in
        return !results.contains(false)
}

It is a combined version of this which is equivalent:

let imageUploads: Driver<[Driver<Bool>]> = Driver.combineLatest(bidID, newBid) { bidID, newBid in
    newBid.uploadedImages.map {
        CustomerManager.shared.bidUploadFile(image: $0, bidID: bidID).asDriver(onErrorJustReturn: false)
    }
}

let photosSaved: Driver<[Bool]> = imageUploads.flatMap { imageUploads in
    return Driver.zip(imageUploads).trackActivity(activityIndicator).asDriver(onErrorJustReturn: [])
}

saveCompleted = photosSaved.map{ (results:[Bool]) -> Bool in
    return !results.contains(false)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.