2017-05-26 5 views
3

Wie kann ich sicherstellen, dass ein Teilnehmer an einem Observable das Ereignis onNext nach einem anderen Abonnenten erhalten?RxSwift Shared Subscription Execution Order

Mein Beispiel ist die folgende:

let firstNameObservable = firstName.asObservable().shareReplay(1) 
let lastNameObservable = lastName.asObservable().shareReplay(1) 
let bioObservable = bio.asObservable().shareReplay(1) 
let websiteObservable = website.asObservable().shareReplay(1) 

firstNameObservable.subscribe(onNext: { [unowned self] firstName in self.accountDetails.firstName = firstName }).disposed(by: disposeBag) 
lastNameObservable.subscribe(onNext: { [unowned self] lastName in self.accountDetails.lastName = lastName }).disposed(by: disposeBag) 
bioObservable.subscribe(onNext: { [unowned self] bio in self.accountDetails.bio = bio }).disposed(by: disposeBag) 
websiteObservable.subscribe(onNext: { [unowned self] website in self.accountDetails.website = website }).disposed(by: disposeBag) 

Observable.combineLatest(firstNameObservable, lastNameObservable, bioObservable, websiteObservable) 
    { [unowned self] _, _, _, _ in return self.accountDetails.validForSignUp } 
    .bind(to: isValid) 
    .disposed(by: disposeBag) 

Ich würde für die letzten combineLatest wie nach jedem der 4 subscriptions auszulösen Bindung oben bereits ausgeführt hat. Dies liegt daran, dass die erst nach der Einstellung der Eigenschaften auf accountDetails korrekt ist.

Ich bin mir bewusst, dass eine Lösung für dieses Problem wäre validForSignUp eine Variable und beobachten Sie es, aber nehmen wir an, dass das nicht möglich ist.

+0

Ist 'isValid' eine' Variable'? Sie sollten Variablen und Themen möglichst vermeiden. –

Antwort

2

Ich würde etwas mehr tun, wie folgt:

let accountDetails = AccountDetails(firstName: firstName.orEmpty.asObserable(), lastName: lastName.orEmpty.asObservable(), bio: bio.orEmpty.asObservable(), website: website.orEmpty.asObservable()) 

accountDetails.validForSignup 
    .bind(to: isValid) 
    .disposed(by: bag) 

struct AccountDetails { 

    let validForSignup: Observable<Bool> 

    init(firstName: Observable<String>, lastName: Observable<String>, bio: Observable<String>, website: Observable<String>) { 

     let firstNameValid = firstName.map { $0.isValidFirstName } 
     let lastNameValid = lastName.map { $0.isValidLastName } 
     let bioValid = bio.map { $0.isValidBio } 
     let websiteValid = website.map { $0.isValidWebsite } 

     validForSignup = Observable.combineLatest([firstNameValid, lastNameValid, bioValid, websiteValid]) { $0.allTrue() } 
    } 
} 

extension String { 
    var isValidFirstName: Bool { 
     return !isEmpty // put approprate code here 
    } 

    var isValidLastName: Bool { 
     return !isEmpty // put approprate code here 
    } 

    var isValidBio: Bool { 
     return !isEmpty // put approprate code here 
    } 

    var isValidWebsite: Bool { 
     return !isEmpty // put approprate code here 
    } 

} 

extension Sequence where Iterator.Element == Bool { 

    func allTrue() -> Bool { 
     return !contains(false) 
    } 
} 
+0

Vielleicht ist die Lösung für dieses Problem in der Tat ein anderer Ansatz. Danke für die Antwort. –

+0

Ja, wenn Sie Ihren reaktiven Code so schreiben, dass die Reihenfolge auf diese Weise zählt, dann machen Sie es falsch. –

1

Sie Ihre Datenvalidierung mit einem einzigen abonnieren umgehen kann. So kann es gemacht werden, wenn ich die kombinierten Ereignisse an ein Observable binden möchte, das die kombinierten Ergebnisse validiert.

Das Observable, das die Validierung der kombinierten Ergebnisse liefern wird, könnte in etwa wie die folgende Funktion aussehen.

func validateFields<T>(allFields: Observable<[T]>) -> Observable<Bool> 
{ 
    return allFields.map { fieldData in 
     var result: Bool = false 

     /* Is the data valid? */ 

     return result; 
    } 
} 

die beobachtbaren validFields wird jedes Mal gibt es neue Daten von einem des Feld Observable mit einem Prüfungsergebnis aktualisiert werden. Mit combineLatest haben Sie den zusätzlichen Vorteil, dass die Reihenfolge Ihrer Quell-Observablen erhalten bleibt. Diese Lösung wird erreicht, ohne auf die Speicherung des Zustands zurückzugreifen, wodurch sie vollständig reaktiv wird.

+0

Mein Ziel war es tatsächlich, die Ausführung der Validierung nach der Einstellung der 'AccountDetails'-Eigenschaften sicherzustellen. Während Ihre Antwort interessant ist, gibt es mir nicht unbedingt eine Lösung für mein spezifisches Problem. –