Я пытаюсь загрузить несколько фотографий на сервер с помощью ReactiveX (RxSwift), собирать ответы от каждого запроса и затем сделать один окончательный запрос для завершения подачи.Управление несколькими добавлениями с помощью ReactiveX (на iOS с Swift и Alamofire)
Все, кажется, работает достаточно хорошо, пока я не попытаюсь ответить reduce
на все ответы. Финал subscribeNext
никогда не вызывается. (Возможно, я не понимаю, как работает flatMap
или reduce
?)
В частности, я пытаюсь выполнить эту процедуру.
Приготовьте наблюдаемый для кодирования каждой фотографии (
self.imageMgr
является экземпляромPHCachingImageManager()
)func getPhotoDataObservable(asset: PHAsset) -> Observable<NSData> { return create { observer in self.imageMgr.requestImageForAsset(asset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: { (myImage, myInfo) -> Void in let data = UIImageJPEGRepresentation(myImage!, 1.0)! NSLog("Encoded photo") observer.onNext(data) self.converts += 1 if self.converts == self.userReview.photos.count { NSLog("Completed encoding photos") observer.onCompleted() } }) return NopDisposable.instance } }
Подготовка наблюдаемого для загрузки каждой фотографии когда-то закодированная (с Alamofire и RxAlamofire)
func getPostPhotoObservable(photoData: NSData) -> Observable<ReviewPhotoObject> { return create { observer in NSLog("Uploading Photo") upload(.POST, urlRequest.URLString, headers: nil, multipartFormData: { mfd in mfd.appendBodyPart(data: photoData, name: "image", fileName: "image", mimeType: "image/jpeg") }, encodingMemoryThreshold: Manager.MultipartFormDataEncodingMemoryThreshold, encodingCompletion: { encodingResult in switch encodingResult { case .Success(let upload, _, _): upload.responseJSON(completionHandler: { (myResponse) -> Void in if let photoResponse = myResponse.result.value { let photoObject = photoResponse.objectForKey("photo")! let photo = ReviewPhotoObject() photo.photoID = photoObject.objectForKey("id")! as! NSNumber NSLog("Uploaded Photo") observer.onNext(photo) } self.uploads += 1 if self.uploads == self.userReview.photos.count { NSLog("Completed uploading photos") observer.onCompleted() } }) case .Failure(let encodingError): observer.onError(encodingError) print(encodingError) } }) return NopDisposable.instance } }
И наконец, все вместе
func postReview(review: MyReview) { self.userReview = review _ = review.photos.toObservable().flatMap { photos in return self.getPhotoDataObservable(photos) }.flatMap { photoData in return self.getPostPhotoObservable(photoData) }.reduce([], { var accumulator, photo: ReviewPhotoObject) -> [Int] in accumulator.append(Int(photo.photoID)) return accumulator }).subscribeNext({ (photoIds) -> Void in print(photoIds) // Never called }) }
При запуске (с 2-х фотографий, например), это выход:
Encoded photo
Uploading photo
Encoded photo
Uploading photo
Completed encoding photos
Uploaded photo
Uploaded photo
Completed uploading photos
Но subscribeNext
никогда не вызывается. Поскольку документация на RxSwift специально по-прежнему немного тонкая, я надеялся, что кто-то здесь может понять меня в том, что я недопонимаю.
Я не знал, как работают наблюдаемые. Я должен был бы вызвать 'onComplete()' сразу после 'onNext()' в этом случае. Я оставлю этот вопрос без ответа, чтобы дать более опытному реактивному программисту шанс объяснить лучше, чем я сейчас могу. (Я отвечу позже после немного большего изучения) –