SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
15.11.2024

Lição: 33: Fechamentos Avançados (Capturando Valores)

No Swift, fechamentos são blocos de funcionalidade autocontidos que podem ser passados e utilizados no seu código. Uma das características poderosas dos fechamentos é a sua capacidade de capturar e armazenar referências a variáveis e constantes do contexto ao seu redor onde foram definidos. Esse comportamento é conhecido como captura de valores.

Nesta aula, vamos explorar o conceito de captura de valores em fechamentos, como isso funciona e suas aplicações práticas.

Compreendendo a Captura de Valores

Quando você cria um fechamento, ele pode capturar e armazenar referências a variáveis e constantes de seu contexto envolvente. Isso significa que, mesmo que essas variáveis saiam do escopo, o fechamento mantém suas próprias cópias dessas variáveis.

Aqui está um exemplo simples para ilustrar isso:

func criaIncrementador(quantidadeIncremento: Int) -> () -> Int {
    var total = 0

    // O fechamento captura a variável `total` e `quantidadeIncremento`
    let incrementador: () -> Int = {
        total += quantidadeIncremento
        return total
    }

    return incrementador
}

let incrementaPorDois = criaIncrementador(quantidadeIncremento: 2)

print(incrementaPorDois()) // Saída: 2
print(incrementaPorDois()) // Saída: 4
print(incrementaPorDois()) // Saída: 6

Nesse exemplo, a função criaIncrementador retorna um fechamento que incrementa uma variável total por uma quantidadeIncremento especificada. Mesmo após a execução da função criaIncrementador, o fechamento incrementador mantém uma referência a total e quantidadeIncremento. Cada vez que chamamos incrementaPorDois, ele atualiza e retorna o total.

Capturando Valores em Tipos de Referência

Os fechamentos também podem capturar tipos de referência, como classes. Ao capturar um tipo de referência, o fechamento mantém uma referência forte ao objeto, o que pode levar a ciclos de retenção se não for gerenciado corretamente.

Aqui está um exemplo com uma classe:

class Contador {
    var contagem = 0

    lazy var incrementador: () -> Int = {
        self.contagem += 1
        return self.contagem
    }
}

let contador = Contador()
print(contador.incrementador()) // Saída: 1
print(contador.incrementador()) // Saída: 2
print(contador.incrementador()) // Saída: 3

Neste caso, a classe Contador possui uma propriedade lazy chamada incrementador que captura self, permitindo que incrementemos a propriedade contagem. O fechamento captura self de forma forte, o que normalmente é seguro neste contexto, mas requer um cuidado especial em cenários mais complexos para evitar vazamentos de memória.

Capturando Valores e Fechamentos Escapáveis

Quando um fechamento é definido como escapável, isso significa que o fechamento pode sobreviver ao escopo da função na qual foi passado, potencialmente levando a situações onde os valores capturados precisam ser gerenciados com cuidado.

Aqui está um exemplo usando um fechamento escapável:

var manipuladorDeConclusao: (() -> Void)?

func fazAlgoAssíncrono(conclusao: @escaping () -> Void) {
    manipuladorDeConclusao = conclusao
}

fazAlgoAssíncrono {
    print("Operação assíncrona concluída!")
}

// Chame o manipulador de conclusão mais tarde
manipuladorDeConclusao?()

Neste exemplo, fazAlgoAssíncrono aceita um fechamento escapável como parâmetro, permitindo que o armazenemos em manipuladorDeConclusao. O fechamento captura o contexto ao seu redor, e podemos invocá-lo mais tarde quando a tarefa assíncrona for concluída.

Conclusão

A captura de valores é um recurso fundamental dos fechamentos em Swift que permite poderosas abstrações e encapsulamentos no seu código. Compreender como os fechamentos capturam variáveis e constantes do seu contexto é crucial para escrever um código Swift eficaz.

À medida que você trabalha mais com fechamentos, tenha em mente as implicações da captura de valores, especialmente em contextos onde tipos de referência estão envolvidos, e ao lidar com fechamentos escapáveis para evitar problemas de gerenciamento de memória. Experimente os exemplos fornecidos para se familiarizar com esses conceitos, e você se tornará mais confortável usando fechamentos em suas aplicações Swift.

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!