【问题标题】:RxSwift: tap a button to do a request with Alamofire, how to make it work?RxSwift:点击一个按钮用 Alamofire 发出请求,如何使它工作?
【发布时间】:2019-11-13 09:48:06
【问题描述】:

我有一些 UI rx 按钮点击,我想将它连接到网络 rx 部分。

这里是 Rx btn tap 部分:

btn.rx.tap.take(1).flatMap {  [unowned self]  () -> Observable<Bool>  in
            // ...
            return NetManager.standard.request()
        }.debug().do(onNext: { _ in
                print("The data flows here")
            }).flatMapLatest { (echo: Bool) -> Observable<Bool> in
            if echo{
                if let app = UIApplication.shared.delegate as? AppDelegate{
                    app.goHome()
                }
                return Observable.of(true)
            }
            else{
                return Observable.of(false)
            }
        }.subscribe(onNext: { (result) in
            // ... , do sth with result
        }).disposed(by: rx.disposeBag)

这是 Alamofire 的网络请求部分:

class NetManager: NSObject {
    
    static let standard = NetManager()
    var dataRequest: DataRequest?
    
    func request() -> Observable<Bool> {
           return Observable<Bool>.create{ (observer) -> Disposable in
                    let data = // ...
                    // ...
                    self.dataRequest = AF.request(aURL, method: HTTPMethod.post, parameters: data, encoder: JSONParameterEncoder.prettyPrinted, headers: aHead).response { (response: DataResponse<Data?>) in
                            self.hud?.hide()
                           if let data = response.data{
                               observer.onNext(true)
                                // ....
                           }
                           else{
                               observer.onNext(false)
                           }
                       }
                    observer.onCompleted()
                    return Disposables.create{}
           }
       }
    
}

这里是调试信息:

Controller.swift:141 (viewDidLoad()) -> 订阅

Controller.swift:141 (viewDidLoad()) -> 事件完成

Controller.swift:141 (viewDidLoad()) -> isDisposed

结果是,do( next ) 部分似乎没有被调用。因为控制台中没有print


问题是,如何让 rx 逻辑工作?


这是我尝试过的:

btn.rx.tap.flatMap 转为btn.rx.tap.take(1).flatMap

因为来自this issue

如果 flatMap 完成将终止外部流,则意味着不会在您的流中注册更多的按钮点击,这实际上没有意义。


来自this question

  btn.rx.tap.map { () -> Observable<Bool> in

    return NetManager.standard.request()
  }.flatMapLatest { (observer: Observable<Bool>) -> Observable<Bool> in
  
    // of cource, I can subscribe to observer
    /*
     observer.subscribe(onNext: { (echo) in
         
     })
     */
    
    
    // how to get the event element elegantly.
    
    return Observable.of(false)
}.subscribe(onNext: { (_) in
    
}).disposed(by: rx.disposeBag)

如何更优雅地做到这一点。

【问题讨论】:

    标签: ios swift rx-swift


    【解决方案1】:

    这里的主要问题是在执行网络请求时,您并没有等待网络调用响应。所以observer.onComplete()observer.onNext()之前触发

    class NetManager: NSObject {
    
    static let standard = NetManager()
    var dataRequest: DataRequest?
    
    func request() -> Observable<Bool> {
           return Observable<Bool>.create { (observer) -> Disposable in
                    let data = // ...
                    // ...
                    self.dataRequest = AF.request(aURL, method: HTTPMethod.post, parameters: data, encoder: JSONParameterEncoder.prettyPrinted, headers: aHead).response { (response: DataResponse<Data?>) in
                            self.hud?.hide()
                           if let data = response.data {
                               observer.onNext(true)
                               // ... 
                           }
                           else {
                               observer.onNext(false)
                           }
                           observer.onComplete() // Moving it here instead will wait for the response
                    }
                    return Disposables.create { }
           }
       }
    }
    

    此时,您的代码应该可以正常工作,但您仍然将一个非常简单的事情复杂化了。

    这里是做什么:

    btn.rx.tap
        .flatMap { _ in
            return NetManager.standard.request()
        }
        .subscribe(onNext: { (success) in
            if success {
                if let app = UIApplication.shared.delegate as? AppDelegate {
                    app.goHome()
                }
            } 
        })
        .disposed(by: rx.disposeBag)
    

    【讨论】:

      猜你喜欢
      • 2019-08-29
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-20
      相关资源
      最近更新 更多