2017-07-10 1 views
0

J'adopte le modèle MVVM dans mon application iOS. J'expose une gamme d'Observables en tant que propriétés publiques dans mon modèle de vue et lie l'interface utilisateur à ces propriétés. Ces Observables sont créés à partir d'un observable connectable privé.RxSwift: Connexion à des multipôles observables connectables

Une classe de contrôleur de vue appelle ensuite la méthode "execute" pour déclencher la requête réseau. Cependant, si cela échoue pour quelque raison que ce soit, j'aimerais pouvoir rappeler "execute" mais cela ne fonctionne pas. Je crois que cela est dû au fait que l'observable connectable est terminée.

Comment puis-je y parvenir sans avoir à recréer le modèle de vue à chaque fois? Je sais que je pourrais le faire en transformant un simple objet de publication execute en userDetailsObservable en utilisant flatMap mais je compte sur l'événement onCompleted pour d'autres fonctionnalités. L'événement onCompleted sera perdu car le sujet de publication reste actif.

Connectable Observable Solution

class ViewModel { 
    public var userName: Observable<String> { 
     self.userDetailsObservable.map { 
      return $0["username"] 
     } 
    } 

    public var address: Observable<String> { 
     self.userDetailsObservable.map { 
      return $0["address"] 
     } 
    } 

    public func execute() { 
     self.userDetailsObservable.connect() 
    } 

    private lazy var userDetailsObservable: ConnectableObservable<JSON> { 
     return Observable.create { observer in 
      // execute network request 
      // assume there is a json object and error object returned 
      if error != nil { 
       observer.onError(error) 
      } else { 
       observer.onNext(json) 
      } 
      observer.onCompleted() 
     }.publish() 
    } 
} 

La solution FlatMap

Cette exécuterait la demande du réseau chaque fois qu'un événement est poussé sur l'exécution sujet. (execute.onNext()). Le problème ici est que l'événement onCompleted est perdu car nous transformons un sujet de publication.

class ViewModel { 
    public var userName: Observable<String> { 
     self.userDetailsObservable.map { 
      return $0["username"] 
     } 
    } 

    public var address: Observable<String> { 
     self.userDetailsObservable.map { 
      return $0["address"] 
     } 
    } 

    public var execute: PublishSubject<Void>() 

    private lazy var userDetailsObservable: Observable<JSON> { 
     return self.execute.flatMapLatest { _ in 
      Observable.create { observer in 
       // execute network request 
       // assume there is a json object and error object returned 
       if error != nil { 
        observer.onError(error) 
       } else { 
        observer.onNext(json) 
       } 
       observer.onCompleted() 
      } 
     }.share() 
    } 

Répondre

1

Vous devez utiliser catchError et retourner une valeur par défaut ("" par exemple).

Il est nécessaire d'empêcher l'observable d'être éliminé lorsque vous recevez une erreur de l'API.