10

私はまだリアクティブ プログラミングと RxSwift 全般の初心者です。2 つの異なる操作を連鎖させたい。私の場合、Web サーバーから zip ファイルをダウンロードして、ローカルで解凍したいだけです。同時に、ダウンロードしたファイルの進行状況も表示したいと思います。そこで、最初のオブザーバブルの作成を開始しました。

 class func rx_download(req:URLRequestConvertible, testId:String) -> Observable<Float> {

    let destination:Request.DownloadFileDestination = ...

    let obs:Observable<Float> = Observable.create { observer in
       let request =  Alamofire.download(req, destination: destination)
        request.progress { _, totalBytesWritten, totalBytesExpectedToWrite in
            if totalBytesExpectedToWrite > 0 {
                observer.onNext(Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
            }
            else {
                observer.onNext(0)
            }
        }
        request.response {  _, response, _, error in
            if let responseURL = response {
                if responseURL.statusCode == 200 {
                    observer.onNext(1.0)
                    observer.onCompleted()
                } else  {
                    let error = NSError(domain: "error", code: responseURL.statusCode, userInfo: nil)
                    observer.onError(error)
                }
            } else {
                let error = NSError(domain: "error", code: 500, userInfo: nil)
                observer.onError(error)
            }

            }
            return AnonymousDisposable () {
                request.cancel()
            }
        }
    return obs.retry(3)

}

その後、解凍用の同様の関数を作成します

class func rx_unzip(testId:String) -> Observable<Float> {
    return Observable.create { observer in
        do {
            try Zip.unzipFile(NSURL.archivePath(testId), destination: NSURL.resourceDirectory(testId), overwrite: true, password: nil)
                {progress in
                    observer.onNext(Float(progress))
                }
        } catch let error {
            observer.onError(error)
        }
        observer.onCompleted()
        return NopDisposable.instance
    }
}

今のところ、「ビューモデルレイヤー」にこのロジックがあるので、ダウンロード->完了時にサブスクライブ->解凍します

私が望むのは、2 つの Observable を 1 つに結合して、最初にダウンロードを実行し、完了したらファイルを解凍することです。これを行う方法はありますか?

4

2 に答える 2

1

operator を使用concatして、これら 2 つの Observable を連鎖させることができます。結果の Observable はnext最初のものから値を送信し、完了すると 2 番目のものから値を送信します。

警告があります: から 0.0 から 1.0 の範囲の進行状況の値を取得しrx_download、再び進行状況がrx_unzip0.0 から始まります。単一の進行状況ビューで進行状況を表示したい場合、これはユーザーを混乱させる可能性があります。

可能なアプローチは、進行状況ビューとともに何が起こっているかを説明するラベルを表示することです。map進捗値と説明テキストを含むタプルにそれぞれ Observable を使用して、 を使用できますconcat。次のようになります。

let mappedDownload = rx_download.map {
    return ("Downloading", $0)
}

let mappedUnzip = rx_download.map {
    return ("Unzipping", $0)
}

mapped1.concat(mapped2)
 .subscribeNext({ (description, progress) in
    //set progress and show description
})

もちろん、考えられる解決策はたくさんありますが、これはコーディングの問題というよりは設計上の問題です。

于 2016-03-11T11:06:09.087 に答える