[英]RxSwift: tap a button to do a request with Alamofire, how to make it work?
我有一些 UI rx 按鈕點擊,我想將它連接到網絡 rx 部分。
這是 Rx btn 抽頭部分:
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
因為從這個問題
如果 flatMap 完成將終止外部 stream,則意味着您的 stream 中將不再注冊按鈕點擊,這實際上沒有意義。
從這個問題看
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)
如何更優雅地做到這一點。
這里的主要問題是在執行網絡請求時,您並沒有等待網絡調用響應。 所以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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.