Salvando a lógica de filtragem no Swift Combine. Parte 2

Combinação orientada a dados





A tradução do artigo foi preparada especialmente para os alunos do curso avançado "iOS Developer" .





No episódio anterior, modelamos com sucesso um fluxo de valores, onde um operador simples ( delay) foi anexado a cada valor .

Nesta parte, examinaremos mais alguns operadores, torná-los Codeablee , finalmente, convertê-los para combinar editor em tempo de execução.



Tipos de Operador


Antes de começarmos a modelá-los, precisamos entender que tipos de operadores existem.

O site da ReactiveX os divide em cerca de 10 categorias: criação, transformação, filtragem, combinação, tratamento de erros, auxiliares, condicionais, matemáticos / agregados, contrapressão, operadores de conversão observáveis ​​e observáveis ​​(To). Se você estiver interessado, o ReactiveX tem uma boa explicação para cada tipo e operador.
Nota: Se você não estiver familiarizado com o RxSwift, o Observable no RxSwift é equivalente ao Publisher in Combine.
Na parte anterior, mencionamos o operador delay, que se refere ao utilitytipo auxiliar ( ). Hoje vamos nos concentrar em preservar dois filteringoperadores de filtragem ( ).



Operadores de filtro


Esse tipo de operador impede que todos ou alguns (ou nenhum) dos elementos de fluxo se movam mais a montante com base nessa condição.

dropFirst


dropFirstinterrompe a transmissão dos primeiros nelementos. Podemos simplesmente adicioná-lo ao nosso enum Operator, dada a sua simplicidade.

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

Também podemos converter facilmente este caso de listagem para o Publisher.

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

Agora o operador dropFirstpode ser salvo e exibido na lista de operadores.



Salvar dropFirsté semelhante a um operador delay. Talvez a filtragem não seja tão diferente dos operadores auxiliares. Bem, vamos tentar outra afirmação antes de chegarmos a essa conclusão.

Filtro


Por outro lado dropFirst, que possui critérios de filtragem muito simples, o operador filterusa o fechamento em vez de um tipo primitivo. Este é um caso mais complicado. Como salvamos e espalhamos um fechamento?

filter(_:)

Publica novamente todos os elementos que correspondem ao fechamento especificado.

developer.apple.com


Vamos dar uma olhada no método filter.

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

Seu fechamento isIncludedassume um tipo universal e retorna um valor booleano.

Existe alguma coisa no Foundation que represente condições lógicas e retorne um valor lógico? Me lembra alguma coisa?

Filtrar com NSPredicate


A resposta é NSPredicate. Se pudermos salvar as condições de filtragem como expressões no formato de sequência, podemos simplesmente transmitir o valor do fluxo e usá-lo NSPredicatepara avaliar os resultados.

Vamos continuar e adicionar filterà lista.

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

Tudo o que precisamos fazer é filtrar expressões como %d !=3ou %@ != “D”; portanto, expressão é um tipo apropriado. Da mesma forma, devemos poder mover a listagem filter para o Publisher.

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

Conforme planejado, enviamos a expressão para NSPredicatejunto com o valor enviado do Publisher.

Observe que NSPredicateaceita uma matriz de argumentos. Portanto, ele deve funcionar com algumas modificações, mesmo quando os valores assumem o formato de tuplas, o que é muito comum em cenários reativos. Voltaremos a isso no futuro quando falarmos sobre operadores combinados.



Como você pode ver, o Fluxo de Filtro é adicionado a essa matriz salva de instruções e convertido no Publisher para filtrar o número 3 dos valores mais altos.



No próximo episódio: Salvando operadores de transformação, mapa e varredura


Na demonstração do GIF, você pode achar que a lista de operadores está bem vazia. Nas próximas semanas, vamos preenchê-lo com vários tipos de operadores: operadores de transformação mape scan.
Você pode encontrar o código-fonte neste repositório combine-magic-swifui na pasta combine-playground.

Aguardamos seus comentários e convidamos você a abrir o dia no curso .

All Articles