English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Neste artigo, você aprenderá o que são闭包, a sintaxe e os tipos de闭包no Swift através de exemplos.
No artigo sobre funções do Swift, usamos a palavra-chave func para criar uma função. No entanto, o Swift também possui outro tipo especial de função chamado闭包, que pode ser definido sem a palavra-chave func e o nome da função.
Como as funções, os闭包podem aceitar parâmetros e retornar valores. Eles também contêm um conjunto de instruções que são executadas após a chamada e podem ser atribuídos a variáveiscomo funções./Constantes.
Os闭包no Swift são semelhantes aos de C e Objective-C.-Os bloco de código no C e as funções anônimas em outros linguagens de programação são muito semelhantes.
As funções globais e as funções aninhadas são na verdade闭包especiais.
As formas de encerramento são:
Função global | Função aninhada | Expressão de encerramento |
Com nome, mas não pode capturar nenhum valor. | Com nome, também pode capturar valores dentro da função encerrada. | Encerramento sem nome, usando sintaxe leve, pode capturar valores do ambiente contextual. |
Existem muitos pontos de otimização dos encerramentos no Swift:
Infere o tipo de parâmetro e de retorno com base no contexto
Retorna implicitamente da expressão de encerramento de uma linha (ou seja, o corpo do encerramento tem apenas uma linha de código e pode omitir return)
Pode usar nomes de parâmetros abreviados, como $0, $1(a partir de 0, representando o i-ésimo parâmetro...)
Fornecido com sintaxe de encerramento de cauda (Trailing closure syntax)
A seguinte definição de encerramento define um parâmetro e retorna o tipo especificado:
{(parameters) -> return type in statements }
let simpleClosure = { print("Olá, Mundo!") } simpleClosure()
O resultado de execução do programa acima é:
Olá, Mundo!
A seguinte forma de encerramento recebe dois parâmetros e retorna um valor booleano:
{(Int, Int) -> Bool in Statement1 Statement 2 --- Statement n }
let simpleClosure: (String) -> (String) = { name in let greeting = "Olá, Mundo!" + "Program" return greeting } let result = simpleClosure("Olá, Mundo") print(result)
O resultado de execução do programa acima é:
Olá, Mundo! Program
Expressão de encerramento é uma maneira de construir uma função anônima com sintaxe concisa. A expressão de encerramento oferece algumas otimizações de sintaxe, tornando a escrita de funções mais simples e clara.
A biblioteca padrão do Swift fornece uma chamada chamada sorted(by:) O método, com base na função de encerramento fornecida para a ordenação, ordenará os valores do array de tipo conhecido.
Após a ordenação, o método sorted(by:) retornará um novo array do mesmo tamanho que o array original, contendo elementos do mesmo tipo e ordenados corretamente. O array original não será modificado pelo método sorted(by:)
O método sorted(by:) precisa passar dois parâmetros:
Array de tipo conhecido
Função de encerramento, essa função de encerramento precisa passar dois valores do mesmo tipo que os elementos do array e retornar um valor booleano para indicar se, após a ordenação, o primeiro parâmetro inserido está antes ou depois do segundo parâmetro. Se o valor do primeiro parâmetro aparecer antes do valor do segundo parâmetro, a função de encerramento de ordenação precisa retornar true, ao contrário, retorna false.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] // Usar função comum (ou função aninhada) para fornecer função de classificação, o tipo da função do encerramento deve ser (String, String) -> Bool. func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } var reversed = names.sorted(by: backwards) print(reversed)
O resultado de execução do programa acima é:
["S", "D", "BE", "AT", "AE"]
se a primeira string (s1), é maior que a segunda string (s2), a função backwards retorna true, indicando que s1deve aparecer em s2antes. Para os caracteres de uma string, "maior" significa "aparecer mais tarde em ordem alfabética". Isso significa que a letra "B" é maior que a letra "A", a string "S" é maior que a string "D". Isso fará a ordenação inversa das letras, "AT" ficará antes de "AE".
O Swift fornece automaticamente a funcionalidade de abreviação de nomes de parâmetros para funções aninhadas, você pode passar diretamente $0, $1,2para chamar os parâmetros do encerramento em ordem.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: { $0 > $1 }) print(reversed)
$0 e $1representa os primeiros e segundos parâmetros do tipo String.
O resultado de execução do programa acima é:
["S", "D", "BE", "AT", "AE"]
Se você usar abreviações de nomes de parâmetros em uma expressão de encerramento, você pode omitir a definição deles na lista de parâmetros do encerramento e o tipo das abreviações de nomes dos parâmetros será inferido pelo tipo da função. A palavra-chave in também pode ser omitida.
Na verdade, há uma maneira ainda mais curta de escrever a expressão de encerramento no exemplo acima.
do SwiftString
O tipo define informações sobre o sinal de maior (>
) implementação de string, que como uma função aceita doisString
parâmetros e retornaBool
valores do tipo.
E isso coincide comsort(_)
O segundo parâmetro do método precisa ser do tipo de função correspondente.
Portanto, você pode simplesmente passar um sinal de maior, o Swift pode inferir automaticamente que você deseja usar a implementação de função de string com sinal de maior:
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: >) print(reversed)
O resultado de execução do programa acima é:
["S", "D", "BE", "AT", "AE"]
Um encerramento subsequente é uma expressão de encerramento escrita após os parênteses de uma função, que suporta chamá-lo como o último parâmetro.
func someFunctionThatTakesAClosure(closure: () -> Void) { // parte do corpo da função } // Aqui está a chamada de função sem usar encerramento subsequente someFunctionThatTakesAClosure({ // Parte principal do encerramento ) // Aqui está a chamada de função usando encerramento subsequente someFunctionThatTakesAClosure() {}} // Parte principal do encerramento }
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] //Encerramento de cauda var reversed = names.sorted() { $0 > $1 } print(reversed)
Depois de sort() { $0 > $1} como encerramento de cauda.
O resultado de execução do programa acima é:
["S", "D", "BE", "AT", "AE"]
Atenção:
Se a função precisar apenas de um parâmetro de expressão de encerramento, quando você usar o encerramento de cauda, você pode até omitir()
Omitido.
reversed = names.sorted { $0 > $1 }
O encerramento pode capturar constantes ou variáveis no contexto de sua definição.
Mesmo que o domínio original dos valores das constantes e variáveis já não exista, o encerramento ainda pode referenciar e modificar esses valores dentro do corpo do encerramento.
A forma mais simples de encerramento no Swift é a função aninhada, que é uma função definida dentro do corpo de outra função.
As funções aninhadas podem capturar todos os parâmetros e constantes ou variáveis definidas nas funções externas.
Veja este exemplo:
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor }
Uma função makeIncrementor, que tem um parâmetro do tipo Int chamado amout, e um parâmetro externo chamado forIncremet, o que significa que você deve usar esse nome externo ao chamá-la. O valor de retorno é um()-> Int
da função.
No corpo da função, foram declaradas as variáveis runningTotal e uma função incrementor.
A função incrementor não recebe nenhum parâmetro, mas acessa as variáveis runningTotal e amount dentro do corpo da função. Isso é porque ele realiza isso capturando as variáveis runningTotal e amount que já existem no corpo da função que a contém.
Como não foi modificado o valor da variável amount, o incrementor realmente captura e armazena uma cópia dessa variável, e essa cópia é armazenada junto com o incrementor.
Portanto, quando chamamos essa função, acumulamos:
import Cocoa func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: 10) // O valor retornado é10 print(incrementByTen()) // O valor retornado é20 print(incrementByTen()) // O valor retornado é30 print(incrementByTen())
O resultado de execução do programa acima é:
10 20 30
No exemplo acima, incrementByTen é uma constante, mas esses encerramentos apontados ainda podem aumentar o valor das variáveis capturadas.
Isso porque a função e o encerramento são tipos de referência.
Independentemente de você passar a função/Seja você atribua o encerramento a uma constante ou a uma variável, na verdade você está atribuindo uma constante/O valor da variável é configurado para a função correspondente/Referência de encerramento. No exemplo acima, incrementByTen aponta para a referência do encerramento é uma constante, e não o conteúdo do encerramento em si.
Isso também significa que se você atribuir um encerramento a duas constantes diferentes/Variáveis, ambos os valores apontam para o mesmo encerramento:
import Cocoa func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: 10) // O valor retornado é10 incrementByTen() // O valor retornado é20 incrementByTen() // O valor retornado é30 incrementByTen() // O valor retornado é40 incrementByTen() let alsoIncrementByTen = incrementByTen // O valor retornado também é50 print(alsoIncrementByTen())
O resultado de execução do programa acima é:
50