Simultaneidade Swift

Feb 14 2023
Introdução: No Swift, a programação assíncrona está se tornando cada vez mais importante, pois os aplicativos precisam ser capazes de lidar com tarefas de longa duração sem bloquear a interface do usuário. A versão mais recente do Swift, Swift 5.

Introdução:

No Swift, a programação assíncrona está se tornando cada vez mais importante, pois os aplicativos precisam ser capazes de lidar com tarefas de longa duração sem bloquear a interface do usuário. A versão mais recente do Swift, Swift 5.5, introduziu uma série de novos recursos para tornar a programação assíncrona mais fácil e expressiva. Neste artigo, exploraremos a nova sintaxe async/await, tarefas, async let, grupos de tarefas, atores e atores globais, e como cada um desses recursos pode nos ajudar a escrever um código mais eficiente, legível e sustentável.

  1. Assíncrono/Aguardar:

Async/await nos permite escrever funções assíncronas que retornam um valor, sem ter que usar manipuladores de conclusão. A palavra-chave async é usada para marcar uma função como assíncrona e a palavra-chave await é usada para aguardar a conclusão de uma operação assíncrona. Aqui está um exemplo:

func fetchImage() async throws -> UIImage {
 let url = URL(string: "https://example.com/image.jpg")!
 let (data, response) = try await URLSession.shared.data(from: url)
 guard (response as? HTTPURLResponse)?.statusCode == 200 else {
 throw NetworkError.invalidResponse
 }
 return UIImage(data: data)!
}

2 . Tarefas:

No Swift 5.5, as Tarefas são uma nova primitiva de simultaneidade que nos permite representar uma unidade de trabalho que pode ser executada simultaneamente com outras tarefas. As tarefas podem ser usadas para executar trabalho síncrono e assíncrono e podem ser canceladas se não forem mais necessárias.

As tarefas são criadas usando a função Task.init e podem ser executadas usando a função Task.run. Aqui está um exemplo:

let task = Task {
    print("Hello, world!")
}
task.run()

3. Letra assíncrona:

Async let é um novo recurso do Swift 5.5 que nos permite declarar e inicializar variáveis ​​de forma assíncrona. Isso é útil quando precisamos aguardar o resultado de uma operação assíncrona antes de podermos usar uma variável.

Async let é usado prefixando a palavra-chave let com a palavra-chave async. Aqui está um exemplo:

func fetchImage() async throws -> UIImage {
    let url = URL(string: "https://example.com/image.jpg")!
    let (data, _) = try await URLSession.shared.data(from: url)
    let image async = try UIImage(data: data)
    return image
}

4. Grupo de Tarefas:

Os grupos de tarefas são um novo recurso no Swift 5.5 que nos permite executar várias tarefas simultaneamente e esperar que todas sejam concluídas. Os grupos de tarefas são úteis quando temos várias tarefas independentes que podem ser executadas simultaneamente e precisamos esperar que todas sejam concluídas antes de continuar.

Os grupos de tarefas são criados usando a função TaskGroup.init e as tarefas podem ser adicionadas ao grupo usando a função TaskGroup.add. Aqui

let group = TaskGroup<Int, Error>()
for i in 1...10 {
    group.addTask {
        await Task.sleep(1_000_000_000)
        return i * 2
    }
}

do {
    let results = try await group.waitForAll()
    print(results)
} catch {
    print("An error occurred: \(error)")
}

5. Atores:

Atores são um novo recurso no Swift 5.5 que nos permitem escrever código thread-safe de uma forma mais declarativa. Atores são objetos que só podem ser acessados ​​por uma tarefa por vez e usam a passagem de mensagens para se comunicar com outros atores. Os atores podem ser usados ​​para evitar problemas comuns de simultaneidade, como corridas de dados e impasses.

Aqui está um exemplo:

actor BankAccount {
    private var balance: Int

    init(balance: Int) {
        self.balance = balance
    }

    func deposit(amount: Int) {
        balance += amount
    }

    func withdraw(amount: Int) -> Bool {
        if amount <= balance {
            balance -= amount
            return true
        } else {
            return false
        }
    }
}

let account = BankAccount(balance: 100)
Task.detached {
    account.deposit(amount: 50)
}
Task.detached {
    if account.withdraw(amount: 75) {
        print("Withdrawal succeeded")
    } else {
        print("Withdrawal failed")
    }
}

6 . Atores Globais:

Atores globais são um novo recurso no Swift 5.5 que nos permite escrever código concorrente de uma forma mais declarativa. Um ator global é um tipo especial de ator que pode ser acessado por qualquer tarefa no sistema. Atores globais podem ser usados ​​para garantir que determinados tipos ou funções sejam sempre acessados ​​de maneira thread-safe, sem a necessidade de definir um ator personalizado para cada um.

Aqui está um exemplo:

@globalActor
struct Logger {
    static let shared = Logger()

    func log(_ message: String) {
        print(message)
    }
}

@Logger func logMessage() {
    print("Hello, world!")
}

Task.detached {
    logMessage()
}

Conclusão:

O Swift 5.5 apresenta vários novos recursos que facilitam a escrita de código simultâneo e assíncrono. Async/await simplifica a sintaxe para trabalhar com funções assíncronas, enquanto Task e TaskGroup fornecem uma maneira mais flexível de gerenciar várias operações simultâneas. Por fim, os atores globais facilitam a garantia de que determinados tipos ou funções sejam sempre acessados ​​de maneira segura para threads. Esses recursos devem tornar mais fácil para os desenvolvedores escrever códigos mais eficientes e confiáveis, especialmente ao trabalhar com sistemas simultâneos complexos.