Um dos erros mais comuns no desenvolvimento de aplicativos iOS é um erro de thread que ocorre quando os desenvolvedores tentam atualizar uma interface de usuário de um encerramento. Para resolver este problema, podemos usar DispatchQueue.main e threads .

Neste tutorial, aprenderemos o que são agendadores e como podemos usá-los no desenvolvimento de aplicativos iOS para gerenciar filas e loops. É necessário ter conhecimento prévio de Swift, do framework Combine e do desenvolvimento iOS.

Vamos começar!

O que é um agendador?

De acordo com a documentação do agendador , um agendador é “um protocolo que define quando e onde executar um encerramento ”. Essencialmente, um planejador fornece aos desenvolvedores uma maneira de executar o código em um arranjo específico, ajudando a executar comandos de enfileiramento em um aplicativo.

Os desenvolvedores podem migrar operações de alto volume para uma fila secundária usando agendadores, liberando espaço na fila principal de um aplicativo e atualizando a IU do aplicativo.

Os agendadores também podem otimizar o código que executa comandos em paralelo, permitindo que os desenvolvedores executem mais comandos ao mesmo tempo. Se o código for serial, os desenvolvedores podem executar o código um bit por vez.

Tipos de agendadores

Existem vários tipos de agendadores que vêm integrados com Combine. É importante observar que os agendadores seguem o protocolo do agendador , que pode ser encontrado na documentação do agendador com link acima.

Vejamos alguns programadores populares!

OperationQueue

De acordo com sua documentação, um OperationQueue executa comandos com base em sua prioridade e prontidão. Depois de adicionar uma operação a uma fila, a operação permanecerá em sua fila até terminar de executar seu comando.

Um OperationQueue pode executar tarefas de maneira serial ou paralela, dependendo da própria tarefa. Uma OperationQueue é usada principalmente para tarefas em segundo plano, como atualizar a IU de um aplicativo.

DispatchQueue

Os documentos da Apple definem um DispatchQueue como uma fila first-in-first-out que pode aceitar tarefas na forma de objetos de bloco e executá-los em série ou simultaneamente.

O sistema gerencia o trabalho enviado a um DispatchQueue em um pool de threads. O DispatchQueue não oferece nenhuma garantia sobre qual thread usará para executar uma tarefa, a menos que DispatchQueue represente o thread principal de um aplicativo.

DispatchQueue é freqüentemente citado como uma das maneiras mais seguras de agendar comandos. No entanto, não é recomendado usar um DispatchQueue no Xcode 11 . Se você usar DispatchQueue como agendador no Xcode 11, ele deve ser serial para cumprir os contratos dos operadores do Combine.

ImmediateScheduler

Um ImmediateScheduler é usado para realizar operações assíncronas imediatamente:

 import Combine let InstantScheduler=ImmediateScheduler.shared deixe aNum=[1, 2, 3].publisher .receive (on: InstantScheduler) .sink (receiveValue: { print ("Recebido \ $ 0) no tópico \ (Threa.currentT") t
})

Por exemplo, o bloco de código acima enviará uma saída semelhante ao bloco de código abaixo:

 Recebido 1 no thread  {number=1, name=main}
Recebido 2 no thread  {number=1, name=main}
Recebido 3 no thread  {number=1, name=main}

ImmediateScheduler executa comandos imediatamente no thread atual do aplicativo. O trecho de código acima está sendo executado no thread principal.

RunLoop

O programador RunLoop é usado para executar tarefas em um loop de execução específico. Ações em um loop de execução podem ser inseguras porque RunLoops não são thread-safe. Portanto, usar um DispatchQueue é a melhor opção.

Agendadores padrão

Se você não especificar um agendador para uma tarefa, o Combine fornece um agendador padrão para ela. O agendador fornecido usará o mesmo encadeamento onde a tarefa é executada. Por exemplo, se você realizar uma tarefa de IU, o Combine fornece um agendador que recebe a tarefa no mesmo encadeamento de IU.

Alternando agendadores

No desenvolvimento iOS usando Combine, muitas tarefas que consomem recursos são feitas em segundo plano, evitando que a IU do aplicativo congele ou falhe completamente. Combine, então, alterna agendadores, fazendo com que o resultado da tarefa seja executado no encadeamento principal.

Combine usa dois métodos integrados para alternar agendadores: receive (on) e subscribe (on) .

receive(on)

O método receive (on) é usado para emitir valores em um planejador específico. Ele muda um programador para qualquer editor que vier depois de ser declarado, conforme visto no bloco de código abaixo:

 Just (3) .map {_ em impressão (Thread.isMainThread)} .receive (on: DispatchQueue.global ()) .map {print (Thread.isMainThread)} .sink {print (Thread.isMainThread)}

O bloco de código acima imprimirá o seguinte resultado:

 verdadeiro
falso
falso

subscribe(on)

O método subscribe (on) é usado para criar uma assinatura em um agendador específico:

 import Combine
print ("Tópico atual \ (Thread.current)")
deixe k=[a, b, c, d, e].publisher .subscribe (em: aQueue) .sick (receiveValue: { print ("obteve \ ($ 0) no tópico \ (Thread.current)") })

O bloco de código acima imprimirá o seguinte resultado:

 Tópico atual  {number=1, name=main}
Recebeu um no thread  {number=7, name=null}
Recebido b no encadeamento  {number=7, name=null}
C recebido no encadeamento  {number=7, name=null}
D recebido no thread  {number=7, name=null}
E recebido no thread  {number=7, name=null}

No bloco de código acima, os valores são emitidos de uma thread diferente em vez da thread principal. O método subscribe (on) executa tarefas em série, conforme visto pela ordem das instruções executadas.

Execução de tarefas assíncronas com agendadores

Nesta seção, aprenderemos como alternar entre os métodos do agendador subscribe (on) e receive (on) . Imagine que um editor está executando uma tarefa em segundo plano:

 struct BackgroundPublisher: Editor Typealias Output=Int typealias Falha=Nunca func receive  (subscriber: K) onde K: Subcriber, Failure==K.Failure, Output==K.Input { dormir (12) assinante. receber (subscriptiton: Subscriptions.empty) _=subscriber.receive (3) subscriber.receive (conclusão: concluído)
}

Se chamarmos a tarefa de um thread da interface do usuário, nosso aplicativo congelará por 12 segundos. Combine irá adicionar um agendador padrão ao mesmo agendador onde nossa tarefa é executada:

 BackgroundPublisher () .sink {_ em impressão ("valor recebido")} imprimir ("Oi!")

No bloco de código acima, Hi! será impresso em nosso console após o valor ser recebido. Podemos ver o resultado abaixo:

 valor recebido
Oi!

No Combine, esse tipo de trabalho assíncrono é frequentemente executado por meio da inscrição em um agendador de segundo plano e do recebimento de eventos em um agendador de IU:

 BackgroundPublisher () .subscribe (em: DispatchQueue.global ()) .receive (em: DispatchQueue.main) .sink {_ in print ("Valor recebido")} imprimir ("Olá de novo!")

O snippet de código acima imprimirá o resultado abaixo:

 Olá de novo!
Valor recebido

Hi Again! é impresso antes do valor ser recebido. Agora, o editor não congela nosso aplicativo bloqueando nosso thread principal.

Conclusão

Nesta postagem, revisamos o que são agendadores e como funcionam nos aplicativos iOS. Cobrimos alguns dos melhores casos de uso para OperationQueue , DispatchQueue , ImmediateScheduler e RunLoop . Também falamos um pouco sobre a estrutura Combine e como ela afeta o uso de agendadores em Swift.

Aprendemos como alternar agendadores em Swift usando os métodos receive (on) e subscribe (on) . Também aprendemos como executar funções assíncronas usando agendadores no Combine, inscrevendo-se em um agendador de segundo plano e recebendo nossos valores em nosso agendador de interface de usuário.

A postagem Compreendendo os programadores Swift apareceu primeiro em LogRocket Blog .