簡體   English   中英

如何直接將UIButton的rx_tap轉換為網絡請求,而無需在嵌套訂閱中發送請求?

[英]How to transform rx_tap of UIButton to a network request directly without sending the request in a nested subscribe?

假設我有一個UIButton loginButton ,我想在使用以下代碼點擊按鈕時發送一個網絡請求:

override func viewDidLoad() {
    super.viewDidLoad()

    let session = self.session // NSURLSession
    loginButton.rx_tap.subscribeNext { [unowned self] in
        session.rx_response(myRequest).subscribe { event in
            switch event {
            case .Next(let data, let response):
                // Handling Response
            case .Error(let error):
                // Handling Error
            default:
                return
            }
        }.addDisposableTo(disposeBag)
     }.addDisposableTo(disposeBag)
}

在這種情況下,即使網絡請求發生錯誤,我也可以通過點擊按鈕重新發送請求。

雖然代碼效果很好,但是由於嵌套訂閱,我認為它有點難看。 我嘗試了flatMap方法來展平訂閱:

loginButton.rx_tap
    .flatMap {
        return session.rx_response(myRequest)
    }
    .subscribe { event in
        switch event {
        case .Next(let data, let response):
            print("Next")
        case .Error(let error):
            print(error)
        default:
            return
        }
     }
     .addDisposableTo(disposeBag)

上面的兩個代碼片段似乎具有不同的邏輯。 后一種訂閱僅在正常訂閱沒有出錯的情況下起作用,而不是在每次點擊按鈕時訂閱網絡請求。

有什么辦法可以壓平正式片段嗎?


添加了嵌套訂閱的代碼段:

loginButton.rx_tap
    .debug("LoginButtonTapped")
    .subscribeNext {
        let disposable = session.rx_response(myRequest)
            .debug("AuthorizationRequest")
            .subscribe(
                onNext: { [unowned self] data, response in
                    // Handling Response
            },
                onError: { [unowned self] error in
                    // Showing Error
            })

        disposable.addDisposableTo(self.disposeBag)

        let alert = UIAlertController(title: "Please Wait.", message: "Requesting Tokens", preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel) { _ in
            disposable.dispose()
            alert.dismissViewControllerAnimated(true, completion: nil)
        })
        self.presentViewController(alert, animated: true, completion: nil)
    }.addDisposableTo(disposeBag)

使用以下代碼可以捕獲錯誤:

let disposable = loginButton.rx_tap
    .map { session.rx_response(request) }
    .flatMap { [unowned self] in $0.catchError(self.presentError) }
    .subscribeNext { data, response in
        // Handling Response
    }

如果需要,我還需要取消網絡請求。 如果我在上述摘要中手動處理disposable ,則訂閱將被處理,我無法再次發送請求。

您有2種方法來實現要求的行為。 第一個是用戶map ,然后switchLatestswitchLatest ,這是經典方法。 第二個是如果您需要按網絡請求順序進行catch / retry ,請使用flatMap用戶。

Ash Furrow在研討會演示代碼中使用第二個示例和Moya給出了一個非常不錯的示例:

    submitButton.rx_tap.map { _ -> Observable<MoyaResponse> in
        return provider.request(.Image)
    }.flatMap() { obs in
        return obs.filterSuccessfulStatusCodes()
            .mapImage()
            .catchError(self.presentError)
            .filter({ (thing) -> Bool in
                return thing != nil
            })
    }
    .take(1)
    .bindTo(imageView.rx_image)
    .addDisposableTo(disposeBag)

另外,您可以檢查RxSwift存儲庫中Github示例,以了解如何處理這些事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM