2017-01-30 1 views
3

Je commence par MVVM afin de bien séparer le code logique de la vue. Mais j'ai un peu d'inquiétude quant à l'endroit où mettre le code lié de progressHUD en appuyant sur un bouton qui fait une demande.Comment montrer/cacher le progressHUD, avec MVVM et RxSwift dans swift

Avant, je l'habitude de le faire:

//Before 
@IBAction func startRequestTapped() { 
    SVProgressHUD.show() 
    self.apiClient.requestObservable().subscribe(onError: { (error) in 
     SVProgressHUD.hide()      
    }, onCompleted: { 
     SVProgressHUD.hide()           
    }) 
} 

Mais quand je l'utilise MVVM, je fais comme ça:

//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) 
} 

Et parmi cela, je ne sais pas où mettre la le hide ou le show de ProgressHUD.

Répondre

5

réponse Mark est juste, mais je vais vous guider étape par étape.

Faisons supose que vous allez essayez de vous connecter.

  1. Copie ActivityIndicator.swift file dans votre projet.

  2. Dans le 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. Créer une extension de SVProgressHUD: (Je ne sais pas SVProgressHUD bibliothèque, mais ce serait quelque chose comme ça S'il vous plaît corriger si nécessaire.)

    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. Dans votre viewController:

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

Merci, Je n'ai pas pensé à ajouter une extension réactive à une classe existante – user3620372

+0

@Xfreire pouvez-vous expliquer quel est le sens de l'extension? –

1

réponse acceptée mis à jour à Swift 4, RxSwift 4.0.0 et 2.2.2 SVProgressHUD:

3- Extension:

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- Contrôleur:

viewModel.signingIn.asObservable().bind(to: SVProgressHUD.rx.isAnimating).disposed(by: disposeBag)