如何 show/hide progressHUD,在 swift 中使用 MVVM 和 RxSwift
How to show/hide the progressHUD, with MVVM and RxSwift in swift
我从 MVVM 开始,以便很好地将逻辑代码与视图分开。但是我有点担心点击发出请求的按钮时将 progressHUD 相关代码放在哪里。
以前,我曾经这样做过:
//Before
@IBAction func startRequestTapped() {
SVProgressHUD.show()
self.apiClient.requestObservable().subscribe(onError: { (error) in
SVProgressHUD.hide()
}, onCompleted: {
SVProgressHUD.hide()
})
}
但是当我使用 mvvm 时,我确实喜欢这样:
//In the viewModel
public var validateButtonDidTap = PublishSubject<Void>()
init() {
validateButtonDidTap.flatMap { (_)
return self.apiClient.requestObservable()
}
}
// In the viewController
viewDidLoad() {
let tap = self.validateButton.rx.tap
tap.bindTo(self.viewModel.validateButtonDidTap)
}
其中,我不知道将 ProgressHUD 隐藏或显示在哪里。
您可以尝试使用 ActivityIndicator
。
请参阅此处的示例:
https://github.com/RxSwiftCommunity/RxSwiftUtilities
标记答案是正确的,但我将逐步指导您。
假设您要尝试登录。
将 ActivityIndicator.swift file 复制到您的项目中。
在viewModel
:
//MARK: - Properties
/// The http client
private let apiClient: YourApiClient
/// Clousure when button is tapped
var didTappedButton: () -> Void = {}
/// The user
var user: Observable<User>
/// Is signing process in progress
let signingIn: Observable<Bool> = ActivityIndicator().asObservable()
//MARK: - Initialization
init(client: YourApiClient) {
self.client = client
self.didTappedButton = { [weak self] in
self.user = self.apiClient
.yourSignInRequest()
.trackActivity(self.signingIn)
.observeOn(MainScheduler.instance)
}
}
创建 SVProgressHUD 的扩展:(我不知道 SVProgressHUD 库,但它应该是这样的。如果需要请修复它)
extension Reactive where Base: SVProgressHUD {
/// Bindable sink for `show()`, `hide()` methods.
public static var isAnimating: UIBindingObserver<Base, Bool> {
return UIBindingObserver(UIElement: self.base) { progressHUD, isVisible in
if isVisible {
progressHUD.show() // or other show methods
} else {
progressHUD.dismiss() // or other hide methods
}
}
}
}
在你的 viewController
:
@IBAction func startRequestTapped() {
viewModel.didTappedButton()
}
override func viewDidLoad() {
// ...
viewModel.signingIn
.bindTo(SVProgressHUD.rx.isAnimating)
.addDisposableTo(disposeBag)
}
已接受的答案已更新为 Swift 4、RxSwift 4.0.0 和 SVProgressHUD 2.2.2:
3- 分机:
extension Reactive where Base: SVProgressHUD {
public static var isAnimating: Binder<Bool> {
return Binder(UIApplication.shared) {progressHUD, isVisible in
if isVisible {
SVProgressHUD.show()
} else {
SVProgressHUD.dismiss()
}
}
}
}
4- 控制器:
viewModel.signingIn.asObservable().bind(to: SVProgressHUD.rx.isAnimating).disposed(by: disposeBag)
我从 MVVM 开始,以便很好地将逻辑代码与视图分开。但是我有点担心点击发出请求的按钮时将 progressHUD 相关代码放在哪里。
以前,我曾经这样做过:
//Before
@IBAction func startRequestTapped() {
SVProgressHUD.show()
self.apiClient.requestObservable().subscribe(onError: { (error) in
SVProgressHUD.hide()
}, onCompleted: {
SVProgressHUD.hide()
})
}
但是当我使用 mvvm 时,我确实喜欢这样:
//In the viewModel
public var validateButtonDidTap = PublishSubject<Void>()
init() {
validateButtonDidTap.flatMap { (_)
return self.apiClient.requestObservable()
}
}
// In the viewController
viewDidLoad() {
let tap = self.validateButton.rx.tap
tap.bindTo(self.viewModel.validateButtonDidTap)
}
其中,我不知道将 ProgressHUD 隐藏或显示在哪里。
您可以尝试使用 ActivityIndicator
。
请参阅此处的示例: https://github.com/RxSwiftCommunity/RxSwiftUtilities
标记答案是正确的,但我将逐步指导您。
假设您要尝试登录。
将 ActivityIndicator.swift file 复制到您的项目中。
在
viewModel
://MARK: - Properties /// The http client private let apiClient: YourApiClient /// Clousure when button is tapped var didTappedButton: () -> Void = {} /// The user var user: Observable<User> /// Is signing process in progress let signingIn: Observable<Bool> = ActivityIndicator().asObservable() //MARK: - Initialization init(client: YourApiClient) { self.client = client self.didTappedButton = { [weak self] in self.user = self.apiClient .yourSignInRequest() .trackActivity(self.signingIn) .observeOn(MainScheduler.instance) } }
创建 SVProgressHUD 的扩展:(我不知道 SVProgressHUD 库,但它应该是这样的。如果需要请修复它)
extension Reactive where Base: SVProgressHUD { /// Bindable sink for `show()`, `hide()` methods. public static var isAnimating: UIBindingObserver<Base, Bool> { return UIBindingObserver(UIElement: self.base) { progressHUD, isVisible in if isVisible { progressHUD.show() // or other show methods } else { progressHUD.dismiss() // or other hide methods } } } }
在你的
viewController
:@IBAction func startRequestTapped() { viewModel.didTappedButton() } override func viewDidLoad() { // ... viewModel.signingIn .bindTo(SVProgressHUD.rx.isAnimating) .addDisposableTo(disposeBag) }
已接受的答案已更新为 Swift 4、RxSwift 4.0.0 和 SVProgressHUD 2.2.2:
3- 分机:
extension Reactive where Base: SVProgressHUD {
public static var isAnimating: Binder<Bool> {
return Binder(UIApplication.shared) {progressHUD, isVisible in
if isVisible {
SVProgressHUD.show()
} else {
SVProgressHUD.dismiss()
}
}
}
}
4- 控制器:
viewModel.signingIn.asObservable().bind(to: SVProgressHUD.rx.isAnimating).disposed(by: disposeBag)