Speichern der Filterlogik in Swift Combine. Teil 2

Datenorientiertes Kombinieren





Die Übersetzung des Artikels wurde speziell für Studenten des Fortgeschrittenenkurses "iOS Developer" vorbereitet .





In der vorherigen Folge haben wir erfolgreich einen Wertestrom modelliert, bei dem jedem Wert ein einfacher Operator ( delay) zugeordnet wurde .

In diesem Teil werden wir uns einige weitere Operatoren ansehen Codeable, sie erstellen und sie schließlich zur Laufzeit in Combine Publisher konvertieren.



Operatortypen


Bevor wir beginnen, sie zu modellieren, müssen wir verstehen, welche Arten von Operatoren existieren.

Die ReactiveX-Site unterteilt sie in ungefähr 10 Kategorien: Erstellung, Transformation, Filterung, Kombination, Fehlerbehandlung, Hilfs-, bedingte, mathematische / aggregierte, Gegendruck-, Konnektiv-Beobachtbar- und Beobachtbar (To) -Konvertierungsoperatoren. Wenn Sie interessiert sind, hat ReactiveX eine gute Erklärung für jeden Typ und Operator.
Hinweis: Wenn Sie mit RxSwift nicht vertraut sind, entspricht Observable in RxSwift Publisher in Combine.
Im vorherigen Teil haben wir den Operator erwähnt delay, der sich auf den utilityTyp auxiliary ( ) bezieht . Heute konzentrieren wir uns auf die Beibehaltung von zwei filtering ( filtering) -Operatoren.



Filteroperatoren


Diese Art von Bediener verhindert, dass sich alle oder einige (oder keine) der Strömungselemente basierend auf dieser Bedingung weiter stromaufwärts bewegen.

dropFirst


dropFirststoppt die Übertragung der ersten nElemente. Wir können es Operatoraufgrund seiner Einfachheit einfach zu unserer Aufzählung hinzufügen .

enum Operator {
 case delay(seconds: Double)
 case dropFirst(count: Int)
}

Wir können diesen Auflistungsfall auch problemlos in Publisher konvertieren.

extension Operator {func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> { 
switch self {
   case .dropFirst(let count):
       return publisher.dropFirst(count).eraseToAnyPublisher()
 //   
 }}}

Jetzt kann der Operator dropFirstgespeichert und in der Operatorliste angezeigt werden.



Das Speichern dropFirstähnelt einem Operator delay. Vielleicht unterscheidet sich die Filterung nicht so sehr von den Hilfsoperatoren. Versuchen wir es mit einer anderen Aussage, bevor wir eine solche Schlussfolgerung ziehen.

Filter


Im Gegensatz dazu verwendet dropFirstder Operator, der sehr einfache Filterkriterien hat, den filterAbschluss anstelle eines primitiven Typs. Dies ist ein komplizierterer Fall. Wie speichern und verbreiten wir eine Schließung?

filter(_:)

Veröffentlicht alle Elemente, die dem angegebenen Abschluss entsprechen, erneut.

developer.apple.com


Schauen wir uns die Methode filtergenauer an .

func filter(_ isIncluded: @escaping (Self.Output) -> Bool) -> Publishers.Filter<Self>

Sein Abschluss isIncludednimmt einen universellen Typ an und gibt einen booleschen Wert zurück.

Gibt es irgendetwas in Foundation, das logische Bedingungen darstellt und einen logischen Wert zurückgibt? Erinnert mich an etwas?

Filtern Sie mit NSPredicate


Die Antwort lautet NSPredicate. Wenn wir die Filterbedingungen als Ausdrücke im Zeichenfolgenformat speichern können, können wir einfach den Wert des Streams übergeben und ihn NSPredicatezur Auswertung der Ergebnisse verwenden.

Fahren wir fort und ergänzen filterdie Liste.

enum Operator {
 case delay(seconds: Double)
 case dropFirst(count: Int)
 case filter(expression: String)
}

Alles was wir tun müssen, ist Ausdrücke wie %d !=3oder zu filtern %@ != “D”; Daher ist Ausdruck ein geeigneter Typ. Ebenso sollten wir in der Lage sein, die Liste filter nach Publisher zu verschieben.

extension Operator {
func applyPublisher<T>(_ publisher: AnyPublisher<T, Never>) -> AnyPublisher<T, Never> { 
 switch self {
   case .filter(let expression):
   return publisher.filter { value in
               NSPredicate(format: expression,
                           argumentArray: [value])
                .evaluate(with: nil) }.eraseToAnyPublisher()
      
     //   
 }}}

Wie geplant senden wir den Ausdruck NSPredicatezusammen mit dem vom Publisher gesendeten Wert an.

Beachten Sie, dass NSPredicateein Array von Argumenten akzeptiert wird. Daher sollte es mit einigen Änderungen funktionieren, selbst wenn die Werte das Format von Tupeln annehmen, was in reaktiven Szenarien sehr häufig ist. Wir werden in Zukunft darauf zurückkommen, wenn wir über kombinierte Betreiber sprechen.



Wie Sie sehen können, wird Filter Stream zu diesem gespeicherten Array von Anweisungen hinzugefügt und in Publisher konvertiert, um die Nummer 3 aus den höheren Werten zu filtern.



In der nächsten Folge: Transformationsoperatoren speichern, Karte und Scan


In der GIF-Demo stellen Sie möglicherweise fest, dass die Liste der Operatoren ziemlich leer ist. In den nächsten Wochen werden wir es mit verschiedenen Arten von Operatoren füllen: Transformationsoperatoren mapund scan.
Sie finden den Quellcode in diesem Repository für Mähdrescher-Magie-Swifui im Ordner Mähdrescher-Spielplatz.

Wir freuen uns auf Ihre Kommentare und laden Sie zum Tag der offenen Tür ein .

All Articles