Closures
Closures
Closures é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 1 de 1. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 1 aulas no total.
Introdução
Olá,
Os fechamentos são blocos de código autocontidos. Um fechamento é passado como parâmetro para o código ou pode ser usado dentro do código.
Um fechamento é um tipo de função. Ele pode ser usado passando-o para o código. São semelhantes às funções lambda de outras linguagens de programação.
Gerenciamento de memória
Um dos pontos mais importantes é que um fechamento pode armazenar os valores de constantes e variáveis no contexto em que é definido.
Esse armazenamento é conhecido como captura de valores.
O Swift gerencia a memória para nós durante esse armazenamento.
Tipos de fechamento
Existem tipos de fechamentos.
- Funções globais são fechamentos nomeados. E essas funções não retêm nenhum valor.
- Funções aninhadas podem carregar os valores do nome e da função que as envolve.
- A expressão de fechamento, por outro lado, é um fechamento anônimo e pode armazenar dados do contexto que a envolve usando uma sintaxe simples.
Sintaxe de fechamento
A sintaxe dos fechamentos foi simplificada tanto quanto possível. Os pontos mais importantes são os seguintes.
- Os parâmetros dos fechamentos podem ser inferidos.
- Os valores de retorno podem ser inferidos.
- O retorno do fechamento pode ser feito em uma linha.
- Os nomes dos argumentos podem ser expressos como atalhos, como $ 0 ou $ 1.
- A sintaxe de fechamento final pode ser usada.
Informação
As expressões de fechamento significam escrever fechamentos diretamente no código, com foco na sintaxe e na simplicidade.
Sintaxe de fechamento
Uma sintaxe de fechamento é apresentada no código de exemplo abaixo.
{ (parameters) -> return type in
statements
}
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.
var reversedNames = names.sorted(by: backward)
Sintaxe de fechamento
No entanto, com um fechamento, não precisamos definir um fechamento global nomeado desnecessariamente desse tipo.
Basta definir uma expressão de fechamento simples no parâmetro. Vamos analisar o exemplo.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)
///sorted method takes closure as parameter.Palavra-chave de início
A palavra-chave indica que o corpo do fechamento começa.
Antes de iniciar o corpo, é necessário definir os parâmetros recebidos pelo fechamento e o tipo de retorno.
Inferindo tipos a partir do contexto
Inferindo tipos a partir do contexto
No exemplo acima, a expressão de fechamento pode ser compreendida pela inferência dos parâmetros e do tipo de retorno, pois o método sorted recebe um fechamento.
Portanto, não precisamos defini-los separadamente.
Neste exemplo, como os valores na matriz names são cadeias de caracteres, entende-se que os parâmetros recebidos pelo fechamento serão do tipo cadeia de caracteres.
Da mesma forma, o fechamento relacionado precisa de um tipo booleano para fazer a ordenação; portanto, o tipo de retorno será inferido como booleano.
Exemplo
Isso simplificará o uso a seguir.
A seta também pode ser omitida do código pela inferência do tipo de retorno.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)Sintaxe curta
Usar a sintaxe longa em vez da sintaxe curta é preferível para evitar confundir os leitores do código.
A sintaxe acima pode ser reduzida ainda mais.
O valor de retorno pode ser reduzido na expressão de fechamento, removendo a palavra-chave de retorno.
/*
In this example, the return keyword has been extracted.
It already has single expression.
There is no need to express it as an extra with return.
*/
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)Exemplo
Neste exemplo, a palavra-chave de retorno foi omitida.
Já existe uma única expressão, portanto não é necessário expressá-la separadamente com um retorno.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )Atalho de nome
A sintaxe pode ser reduzida ainda mais. No exemplo acima, declaramos que o fechamento recebe dois parâmetros, incluindo s1 e s2. Os tipos deles são inferidos.
Agora podemos evitar o trabalho de expressar esses parâmetros e também de defini-los, usando atalhos.
Além disso, como não há definição de parâmetros nem passagem de valor de retorno, a palavra-chave de início também pode ser omitida.
let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)
// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.Exemplo reduzido
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.TRAILING CLOSURE
Fechamento final
Se o parâmetro a ser passado para uma função de fechamento for o argumento final da função e a expressão de fechamento for longa, pode ser mais útil escrevê-la como uma instrução de fechamento final.
Podemos usar o fechamento final como açúcar sintático. Ele é usado para aumentar a legibilidade do código.
O último parâmetro da maioria dos métodos do iOS é um fechamento.
Parâmetro final
Por exemplo, neste exemplo, o parâmetro final é um fechamento.
class Animator {
class func animate(withDuration duration: Double, animations: () -> Void) {
animations()
}
}
class MyViewController {
func start() {
// With the traditional method, we can call this fund as follows.
Animator.animate(withDuration: 1, animations: { [unowned self] in
print("red")
})
}
}
MyViewController().start()Como o código acima é menos legível, ele pode ser escrito da seguinte forma
Como o código acima é menos legível, ele pode ser escrito da seguinte forma.
import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")Exemplo
Ao usar a sintaxe de fechamento final, não precisamos escrever um rótulo de argumento.
Isso acontece porque os fechamentos agora se tornaram parte da chamada da função.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}Sintaxe
Na prática, podemos pensar na sintaxe de fechamento final como açúcar sintático. Ela torna o código mais legível.
/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)
// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
self.view.backgroundColor = UIColor.red
})
/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method
is closure, Swift allows to make a call like the one below.
*/
UIView.animate(withDuration: 1) { [unowned self] in
self.view.backgroundColor = UIColor.red
}Podemos usar o código abaixo para testá-lo
Podemos usar o código abaixo para testar o código.
func greetThenRunClosure(name: String, closure: () -> ()) {
print("Hello, \(name)!")
closure()
}
greetThenRunClosure(name: "Paul") {
print("The closure was run")
}Captura de valores pelos fechamentos
Captura de valores pelos fechamentos
Um fechamento pode manter o valor das variáveis que envolvem seu ambiente. Ele pode até alterar o valor dessas variáveis dentro do próprio corpo e acessá-las.
Mesmo que elas não estejam no escopo original em que foram definidas.
Continuação
Em geral, isso significa que os dados podem ser mantidos em funções aninhadas juntamente com expressões de fechamento. Elas podem armazenar os dados da função externa.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30Continuação
Se você atribuir um fechamento como propriedade de uma classe, ele começará a manter as referências desta instância ao fechamento.
Portanto, será estabelecido um ciclo forte de referências entre o fechamento e a instância.
Deve-se prestar atenção especial aos vazamentos de memória.
Aviso
Fechamentos e funções são tipos de referência.
@escaping
Podemos precisar desse uso em muitos pontos nos quais o fechamento é usado de forma assíncrona.
Nas primeiras versões do Swift (1 e 2), os fechamentos nos parâmetros do Swift eram de escape e, posteriormente, tornaram-se sem escape. Se precisássemos passar o fechamento sem escape, teríamos de especificá-lo explicitamente.
Nas versões seguintes, os parâmetros de fechamento passaram a ser sem escape para obter uma vantagem no uso da memória.
Agora, se quisermos definir um fechamento de escape, precisamos usar a palavra-chave @escaping.
@ESCAPING Palavra-chave
@ESCAPING Palavra-chave
Se quisermos poder chamar os fechamentos atribuídos a uma função depois que ela retornar, precisamos marcá-los com a palavra-chave @escaping.
Os fechamentos definidos por padrão para uma função são tipos de referência, mas não incrementam a contagem de referências. Isso ocorre porque, no momento da chamada, o tempo de vida desse fechamento termina, portanto não precisamos incrementar a contagem de referências.
No entanto, se precisarmos do fechamento passado como parâmetro depois que uma função for chamada, talvez seja necessário indicá-lo com a palavra-chave @escaping.
nonEscaping
Primeiro, vamos ver como funciona um fechamento nonEscaping.
Quando esse fechamento é passado como parâmetro para a função, ele é processado no corpo da função e, em seguida, o controle retorna ao compilador.
Depois que a função retorna, isto é, depois que a execução é concluída, ele deixa de estar no escopo do fechamento e é liberado da memória.
Usando um fechamento de escape
Usando um fechamento de escape
Quando um fechamento é passado como argumento, ele continua sendo mantido mesmo depois que a função de fechamento retorna e a execução é concluída.
Ele ocupa espaço na memória até que o fechamento seja executado. Existem vários tipos de fechamentos de escape.
Parabéns
Parabéns 🎉
Chegamos ao final da nossa lição.
Até a próxima lição 😎

Perguntas Frequentes
A aula “Closures” é grátis?
Sim — o texto completo de “Closures” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 1 aulas no total.
O que vou aprender em “Closures”?
Closures Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Swift Academy?
Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 1.
Quanto tempo leva a aula “Closures”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Swift Academy?
Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.