Как показать / скрыть прогресс HUD, с MVVM и RxSwift в быстром
Я начинаю с 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.
3 ответа
Марк ответ правильный, но я буду вести вас шаг за шагом.
Предположим, вы попытаетесь войти.
Скопируйте файл ActivityIndicator.swift в свой проект.
в
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)
Вы можете попробовать использовать ActivityIndicator
,
Смотрите пример здесь: https://github.com/RxSwiftCommunity/RxSwiftUtilities