【问题标题】:How to show/hide the progressHUD, with MVVM and RxSwift in swift如何使用 MVVM 和 RxSwift 快速显示/隐藏 progressHUD
【发布时间】:2017-06-15 10:09:11
【问题描述】:

我从 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 隐藏或显示在哪里。

【问题讨论】:

    标签: ios swift mvvm rx-swift svprogresshud


    【解决方案1】:

    马克答案是正确的,但我会一步一步地指导你。

    假设您要尝试登录。

    1. 在您的项目中复制ActivityIndicator.swift file

    2. 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)
          }
      }
      
    3. 创建一个 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
                  }
              }
          }
      
      }
      
    4. 在你的viewController

      @IBAction func startRequestTapped() {
          viewModel.didTappedButton()
      }
      
      override func viewDidLoad() {
      
          // ...
      
          viewModel.signingIn
                   .bindTo(SVProgressHUD.rx.isAnimating)
                   .addDisposableTo(disposeBag)
      }
      

    【讨论】:

    • 谢谢,我没有考虑在现有类中添加响应式扩展
    • @Xfreire 你能解释一下 where in extension 是什么意思吗?
    • @XFreire:我收到错误 - 无法将 'Observable' 类型的值转换为 .trackActivity(self.signingIn) 行上的预期参数类型 'ActivityIndi​​cator'
    【解决方案2】:

    已接受的答案已更新至 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)
    

    【讨论】:

      【解决方案3】:

      您可以尝试使用ActivityIndicator

      请参见此处的示例: https://github.com/RxSwiftCommunity/RxSwiftUtilities

      【讨论】:

        猜你喜欢
        • 2015-07-15
        • 1970-01-01
        • 2015-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-06
        • 2017-09-03
        • 1970-01-01
        相关资源
        最近更新 更多