English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In questo articolo, imparerai cosa sono i blocchi, la sintassi e i tipi di blocchi in Swift.
Nel testo della funzione Swift, abbiamo creato una funzione utilizzando la parola chiave func. Ma in Swift c'è anche un altro tipo speciale di funzione chiamato blocco, che può essere definito senza la parola chiave func e il nome della funzione.
Come le funzioni, i blocchi possono accettare parametri e restituire valori. Contengono anche un insieme di istruzioni che vengono eseguite dopo la chiamata e possono essere assegnati a variabili o costanti come funzioni.
I blocchi in Swift sono simili ai blocchi in C e Objective-C e a funzioni anonime in altri linguaggi di programmazione.
La funzione globale e la funzione annidata sono in realtà blocchi speciali.
La forma dei blocchi è:
Funzione globale | Funzione annidata | 闭包表达式 |
Blocchi con nome ma non possono catturare alcun valore. | Blocchi con nome, possono anche catturare valori all'interno della funzione chiusa. | Blocchi anonimi, utilizzando una sintassi leggera, possono catturare valori dall'ambiente contestuale. |
Swift ha molte ottimizzazioni per i blocchi:
Inferenza del tipo di parametro e valore di ritorno dal contesto
Il ritorno implicito da espressioni di blocco singole (ovvero il corpo del blocco ha solo una riga di codice e può essere omesso return)
可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)}
提供了尾随闭包语法(Trailing closure syntax)
以下定义了一个接收参数并返回指定类型的闭包语法:
{(parameters) -> return type in statements }
let simpleClosure = { print("Hello, World!") } simpleClosure()
以上程序执行输出结果为:
Hello, World!
以下闭包形式接收两个参数并返回布尔值:
{(Int, Int) -> Bool in Statement1 Statement 2 --- Statement n }
let simpleClosure: (String) -> (String) = { name in let greeting = "Hello, World! " + "Program" return greeting } let result = simpleClosure("Hello, World") print(result)
以上程序执行输出结果为:
Hello, World! Program
闭包表达式是一种利用简洁语法构建内联闭包的方式。闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
Swift 标准库提供了名为 sorted(by:) 的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。
sorted(by:)方法需要传入两个参数:
已知类型的数组
闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回 true,反之返回 false。
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] // 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。 func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } var reversed = names.sorted(by: backwards) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Se la prima stringa (s1) è maggiore della seconda stringa (s2), la funzione backwards restituisce true, il che significa che s1 dovrebbe apparire prima di s2 nell'array nuovo. Per i caratteri delle stringhe, "maggiore" significa "appare più tardi nell'ordine alfabetico". Questo significa che la lettera "B" è maggiore della lettera "A", la stringa "S" è maggiore della stringa "D". Effettuerà una sortita inversa, "AT" apparirà prima di "AE".
Swift fornisce automaticamente la funzione di abbreviazione dei nomi dei parametri per le funzioni inline, puoi chiamare direttamente i parametri della chiusura con $0, $1, $2 in ordine.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: { $0 > $1 }) print(reversed)
$0 e $1 rappresentano il primo e il secondo parametro di tipo String nella chiusura.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Se usi abbreviazioni di nome dei parametri in un'espressione di chiusura, puoi omettere la loro definizione nella lista dei parametri della chiusura e il tipo dell'abbreviazione del nome del parametro sarà inferito dal tipo della funzione. La parola chiave 'in' può anche essere omessa.
In realtà, c'è un modo ancora più breve per scrivere l'espressione di chiusura nell'esempio sopra.
funzione operatore in SwiftString
definisce qualcosa su come usare il maggiore di (>
) implementazione di stringa, che come funzione accetta dueString
parametro e restituisceBool
valori di tipo.
E questo corrisponde asort(_):
Il secondo parametro del metodo richiede un tipo di funzione che corrisponde.
Quindi, puoi semplicemente passare un maggiore di, Swift può inferire automaticamente che vuoi utilizzare l'espressione di funzione di stringa con il maggiore di:
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: >) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Una chiusura trailing è un'espressione di chiusura scritta dopo i parentesi della funzione, che la funzione supporta come ultimo argomento da chiamare.
func someFunctionThatTakesAClosure(closure: () -> Void) { // Corpo della funzione } // Ecco come si chiama una funzione senza chiusura trailing someFunctionThatTakesAClosure({ // Corpo della chiusura } // Ecco come si chiama una funzione con chiusura trailing someFunctionThatTakesAClosure() { // Corpo della chiusura }
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] //Closure trailing var reversed = names.sorted() { $0 > $1 } print(reversed)
La { $0 > $1 } dopo sort() è una closure trailing.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Attenzione:
Se la funzione ha bisogno solo di un'espressione di closure come parametro, quando si utilizza la closure trailing, si può anche mettere()
Saltato.
reversed = names.sorted { $0 > $1 }
Le closures possono catturare costanti o variabili nel contesto in cui sono definite.
Anche se il dominio di origine di queste costanti o variabili non esiste più, le closures possono ancora riferirsi e modificare questi valori all'interno della funzione di closure.
La forma più semplice di closure in Swift è la funzione annidata, ossia la funzione definita nel corpo di un'altra funzione.
Le funzioni annidate possono catturare tutti i parametri e le costanti o le variabili definite nelle funzioni esterne.
Vediamo questo esempio:
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor }
Una funzione makeIncrementor che ha un parametro di tipo Int chiamato amout e un parametro esterno chiamato forIncremet, il che significa che quando la chiama, deve utilizzare questo nome esterno. Il valore di ritorno è un-> Int
di funzione.
All'interno della funzione, è stata dichiarata la variabile runningTotal e una funzione incrementor.
La funzione incrementor non prende alcun parametro, ma accede alle variabili runningTotal e amount all'interno del corpo della funzione. Questo è perché cattura le variabili runningTotal e amount esistenti nel corpo della funzione che la contiene.
Poiché non è stata modificata la variabile amount, incrementor cattura e memorizza una copia di quella variabile, che viene memorizzata insieme a incrementor.
Quindi chiamando questa funzione si accumulerà:
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) //返回的值为10 print(incrementByTen()) //返回的值为20 print(incrementByTen()) //返回的值为30 print(incrementByTen())
以上程序执行输出结果为:
10 20 30
Nel caso di esempio, incrementByTen è una costante, ma queste costanti possono ancora aumentare il valore delle variabili catturate.
Questo è perché le funzioni e le closures sono di tipo riferimento.
Indipendentemente dal fatto che assegni una funzione/closure a una costante o a una variabile, stai effettivamente impostando il valore della costante/variabile come un riferimento alla funzione/closure corrispondente. Nel caso di esempio, incrementByTen punta a un riferimento alla closure che è una costante, non al contenuto della closure stessa.
Questo significa che se assegni un closure a due diverse costanti/variabili, entrambi i valori faranno riferimento allo stesso closure:
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) //返回的值为10 incrementByTen() //返回的值为20 incrementByTen() //返回的值为30 incrementByTen() //返回的值为40 incrementByTen() let alsoIncrementByTen = incrementByTen //返回的值也为50 print(alsoIncrementByTen())
以上程序执行输出结果为:
50