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 Codeable
e , 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 utility
tipo auxiliar ( ). Hoje vamos nos concentrar em preservar dois filtering
operadores 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
dropFirst
interrompe a transmissão dos primeiros n
elementos. 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 dropFirst
pode 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 filter
usa 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 isIncluded
assume 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 NSPredicate
para 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 !=3
ou %@ != “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 NSPredicate
junto com o valor enviado do Publisher.Observe que NSPredicate
aceita 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 map
e 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 .