Manage multiple add-ons with ReactiveX (on iOS with Swift and Alamofire)

I try to upload several photos to the server using ReactiveX (RxSwift), collect responses from each request and then make one final request to complete the submission.

Everything seems to work quite well until I try to complete reduceall the answers. The final one is subscribeNextnever called. (Perhaps I do not understand how they work flatMapor reduce?)

In particular, this is how I try to perform this procedure.

  • Prepare the observable to encode each photo ( self.imageMgris an instance 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
        }
    }
    
  • Prepare each photo you want to upload after encoding (using Alamofire and 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
        }
    }
    
  • Finally all together

    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
        })
    }
    

(, ) :

Encoded photo
Uploading photo
Encoded photo
Uploading photo
Completed encoding photos
Uploaded photo
Uploaded photo
Completed uploading photos

subscribeNext . RxSwift - , , - , .

+4
1

, , , , . PHAsset, , . , , , reduce , , .

( Swift 3 2.)

extension PHImageManager {

    func requestMaximumSizeImage(for asset: PHAsset) -> Observable<UIImage> {
        return .create { observer in
            let request = self.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: nil, resultHandler: { image, info in
                if let image = image {
                    observer.onNext(image)
                    observer.onCompleted()
                }
                else if let info = info, let error = info[PHImageErrorKey] as? Error {
                    observer.onError(error)
                }
            })
            return Disposables.create { self.cancelImageRequest(request) }
        }
    }
}

, PHImageManager , . , , , , . , JPEG. JPEG :

    let imagesData = review.photos.toObservable().flatMap {
        self.imageMgr.requestMaximumSizeImage(for: $0)
    }.map {
        UIImageJPEGRepresentation($0, 1.0)
    }.filter { $0 != nil }.map { $0! }

, JPEG, , . imagesData - Observable<Data>.

getPostPhotoObservable , , , . , Observable , ReviewPhotoObject.

:

  • , , , ReviewPhotoObject , ( , . ) , concat flatMap.

  • - , . , -, - . catchErrorJustReturn, catchError .

+1
source

Source: https://habr.com/ru/post/1619782/


All Articles