Rxswift - 如何显示进度条
Rxswift - how to show a progress bar
我需要在 API 调用时显示进度条,并在 API 调用完成后隐藏它。以下是我编写的用于填充 table 的代码。我应该在哪里调用以显示和隐藏被调用的 API 的进度?有 RxSwift
的方法吗?
items = fetchAllAnswers()
items.bindTo(self.myTableView.rx_itemsWithCellIdentifier("cellIdentifier", cellType: UITableViewCell.self)){ (row, element, cell) in
cell.textLabel?.text = element
}
.addDisposableTo(disposeBag)
func fetchAllAnswers() -> Observable<[String]>{
let api = Observable.create { (obsever: AnyObserver<[String]>) -> Disposable in
//progress.show()
let items = Api.getUsers()
obsever.onNext(items)
obsever.onCompleted()
//progress.hide
return AnonymousDisposable{
print("api dispose called")
}
}
return api
}
你已经在你的 ViewController 中完成了这项工作,像这样:
var disposeBag = DisposeBag()
...
items = fetchAllAnswers()
.subscribeOn(backgroundWorkScheduler)
.observeOn(mainScheduler)
.subscribe(
onNext: { data in
print("onNext")
//show/update progress
},
onCompleted: {
print("onCompleted")
//hide progress
},
onDisposed: {
print("onDisposed")
}
).addDisposableTo(disposeBag)
您可以在我的项目中使用ActivityIndicator from RxSwift repo. I using MBProgressHUD。
首先你需要为这个库创建扩展:
extension MBProgressHUD {
/**
Bindable sink for MBProgressHUD show/hide methods.
*/
public var rx_mbprogresshud_animating: AnyObserver<Bool> {
return AnyObserver { event in
MainScheduler.ensureExecutingOnScheduler()
switch (event) {
case .Next(let value):
if value {
let loadingNotification = MBProgressHUD.showHUDAddedTo(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)
loadingNotification.mode = self.mode
loadingNotification.labelText = self.labelText
loadingNotification.dimBackground = self.dimBackground
} else {
MBProgressHUD.hideHUDForView(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)
}
case .Error(let error):
let error = "Binding error to UI: \(error)"
#if DEBUG
rxFatalError(error)
#else
print(error)
#endif
case .Completed:
break
}
}
}
}
import RxSwift
import RxCocoa
extension Reactive where Base: MBProgressHUD {
public var animation: Binder<Bool> {
return Binder(self.base) { hud, show in
guard let view = UIApplication.shared.keyWindow?.subviews.last()! else { return }
if show {
if hud.superview == nil {
view.addSubview(hud)
}
hud.show(animated: true)
} else {
hud.hide(animated: true)
}
}
}
}
接下来您需要在 ViewController class:
中创建 ActivityIndicator 对象
let progress = MBProgressHUD()
progress.mode = MBProgressHUDMode.Indeterminate
progress.labelText = "Loading..."
progress.dimBackground = true
let indicator = ActivityIndicator()
indicator.asObservable()
.bindTo(progress.rx_mbprogresshud_animating)
.addDisposableTo(bag)
接下来只需在您的序列中使用 trackActivity() 函数:
apiMethod
.trackActivity(indicator)
.subscribeNext { stringArray in
items.value = stringArray
}
.addDisposableTo(bag)
Swift 4
extension MBProgressHUD {
var rx_mbprogresshud_animating: AnyObserver<Bool> {
return AnyObserver { event in
MainScheduler.ensureExecutingOnScheduler()
switch (event) {
case .next(let value):
if value {
let loadingNotification = MBProgressHUD.showAdded(to: (UIApplication.shared.keyWindow?.subviews.last)!, animated: true)
loadingNotification.mode = self.mode
loadingNotification.label.text = self.label.text
} else {
MBProgressHUD.hide(for: (UIApplication.shared.keyWindow?.subviews.last)!, animated: true)
}
case .error(let error):
let error = "Binding error to UI: \(error)"
print(error)
case .completed:
break
}
}
}
}
swift 4.2 && swift 5
// MBProgressHUD+Rx.swift
import RxSwift
import RxCocoa
extension Reactive where Base: MBProgressHUD {
public var animation: Binder<Bool> {
return Binder(self.base) { hud, show in
guard let view = UIApplication.shared.keyWindow else { return }
if show {
if hud.superview == nil {
view.addSubview(hud)
}
hud.show(animated: true)
} else {
hud.hide(animated: true)
}
}
}
}
使用
// hud init
private var hud: MBProgressHUD = {
let progress = MBProgressHUD()
progress.mode = MBProgressHUDMode.indeterminate
progress.label.text = ""
progress.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return progress
}()
// track
some_action.flatMapLatest{
return some_operation1.trackActivity(hudModeIndicator)
}.flatMapLatest{
return some_operation2.trackActivity(hudModeIndicator)
}.drive(onNext: {}).disposed(by: rx.disposeBag)
// bind
hudModeIndicator
.drive(self.hud.rx.animation).disposed(by: rx.disposeBag)
参考
我需要在 API 调用时显示进度条,并在 API 调用完成后隐藏它。以下是我编写的用于填充 table 的代码。我应该在哪里调用以显示和隐藏被调用的 API 的进度?有 RxSwift
的方法吗?
items = fetchAllAnswers()
items.bindTo(self.myTableView.rx_itemsWithCellIdentifier("cellIdentifier", cellType: UITableViewCell.self)){ (row, element, cell) in
cell.textLabel?.text = element
}
.addDisposableTo(disposeBag)
func fetchAllAnswers() -> Observable<[String]>{
let api = Observable.create { (obsever: AnyObserver<[String]>) -> Disposable in
//progress.show()
let items = Api.getUsers()
obsever.onNext(items)
obsever.onCompleted()
//progress.hide
return AnonymousDisposable{
print("api dispose called")
}
}
return api
}
你已经在你的 ViewController 中完成了这项工作,像这样:
var disposeBag = DisposeBag()
...
items = fetchAllAnswers()
.subscribeOn(backgroundWorkScheduler)
.observeOn(mainScheduler)
.subscribe(
onNext: { data in
print("onNext")
//show/update progress
},
onCompleted: {
print("onCompleted")
//hide progress
},
onDisposed: {
print("onDisposed")
}
).addDisposableTo(disposeBag)
您可以在我的项目中使用ActivityIndicator from RxSwift repo. I using MBProgressHUD。 首先你需要为这个库创建扩展:
extension MBProgressHUD {
/**
Bindable sink for MBProgressHUD show/hide methods.
*/
public var rx_mbprogresshud_animating: AnyObserver<Bool> {
return AnyObserver { event in
MainScheduler.ensureExecutingOnScheduler()
switch (event) {
case .Next(let value):
if value {
let loadingNotification = MBProgressHUD.showHUDAddedTo(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)
loadingNotification.mode = self.mode
loadingNotification.labelText = self.labelText
loadingNotification.dimBackground = self.dimBackground
} else {
MBProgressHUD.hideHUDForView(UIApplication.sharedApplication().keyWindow?.subviews.last, animated: true)
}
case .Error(let error):
let error = "Binding error to UI: \(error)"
#if DEBUG
rxFatalError(error)
#else
print(error)
#endif
case .Completed:
break
}
}
}
}
import RxSwift
import RxCocoa
extension Reactive where Base: MBProgressHUD {
public var animation: Binder<Bool> {
return Binder(self.base) { hud, show in
guard let view = UIApplication.shared.keyWindow?.subviews.last()! else { return }
if show {
if hud.superview == nil {
view.addSubview(hud)
}
hud.show(animated: true)
} else {
hud.hide(animated: true)
}
}
}
}
接下来您需要在 ViewController class:
中创建 ActivityIndicator 对象let progress = MBProgressHUD()
progress.mode = MBProgressHUDMode.Indeterminate
progress.labelText = "Loading..."
progress.dimBackground = true
let indicator = ActivityIndicator()
indicator.asObservable()
.bindTo(progress.rx_mbprogresshud_animating)
.addDisposableTo(bag)
接下来只需在您的序列中使用 trackActivity() 函数:
apiMethod
.trackActivity(indicator)
.subscribeNext { stringArray in
items.value = stringArray
}
.addDisposableTo(bag)
Swift 4
extension MBProgressHUD {
var rx_mbprogresshud_animating: AnyObserver<Bool> {
return AnyObserver { event in
MainScheduler.ensureExecutingOnScheduler()
switch (event) {
case .next(let value):
if value {
let loadingNotification = MBProgressHUD.showAdded(to: (UIApplication.shared.keyWindow?.subviews.last)!, animated: true)
loadingNotification.mode = self.mode
loadingNotification.label.text = self.label.text
} else {
MBProgressHUD.hide(for: (UIApplication.shared.keyWindow?.subviews.last)!, animated: true)
}
case .error(let error):
let error = "Binding error to UI: \(error)"
print(error)
case .completed:
break
}
}
}
}
swift 4.2 && swift 5
// MBProgressHUD+Rx.swift
import RxSwift
import RxCocoa
extension Reactive where Base: MBProgressHUD {
public var animation: Binder<Bool> {
return Binder(self.base) { hud, show in
guard let view = UIApplication.shared.keyWindow else { return }
if show {
if hud.superview == nil {
view.addSubview(hud)
}
hud.show(animated: true)
} else {
hud.hide(animated: true)
}
}
}
}
使用
// hud init
private var hud: MBProgressHUD = {
let progress = MBProgressHUD()
progress.mode = MBProgressHUDMode.indeterminate
progress.label.text = ""
progress.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return progress
}()
// track
some_action.flatMapLatest{
return some_operation1.trackActivity(hudModeIndicator)
}.flatMapLatest{
return some_operation2.trackActivity(hudModeIndicator)
}.drive(onNext: {}).disposed(by: rx.disposeBag)
// bind
hudModeIndicator
.drive(self.hud.rx.animation).disposed(by: rx.disposeBag)