Middle
Parla della lista di cattura in Swift.
sobes.tech AI
Risposta dell'AI
L'elenco di cattura in Swift viene utilizzato per gestire esplicitamente la cattura delle variabili da parte delle closure. Questo aiuta a evitare cicli di riferimenti forti, specialmente quando si lavora con self all'interno di closure usate nelle classi. I principali tipi di cattura sono: weak e unowned.
| Tipo di cattura | Descrizione | Quando usarlo |
|---|---|---|
weak |
Cattura la variabile come opzionale, senza aumentare il contatore di riferimenti. Il suo valore può diventare nil. |
Quando l'oggetto della closure può sopravvivere all'oggetto catturato. |
unowned |
Cattura la variabile senza aumentare il contatore di riferimenti, ma si presume che l'oggetto catturato vivrà finché la closure esiste. Non è opzionale. | Quando l'oggetto della closure e l'oggetto catturato hanno la stessa durata di vita, e l'oggetto catturato non sarà nil prima che la closure termini. |
Sintassi della lista di cattura:
{ [lista di cattura] (parametri) -> tipoDiRitorno in
// codice
}
Esempio di utilizzo di weak self:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // Controllo di nil
self.value += 1
print("Il valore ora è \(self.value)")
}
}
}
Esempio di utilizzo di unowned self:
class ViewController: UIViewController {
var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button = UIButton(type: .system)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}
@objc func buttonTapped() {
// unowned self non è necessario in questo caso, poiché il button esiste finché il ViewController esiste.
// Ma se la closure potrebbe sopravvivere al ViewController, unowned potrebbe essere appropriato se
// si è sicuri che self non diventerà nil.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Può catturare non solo self, ma anche qualsiasi altra variabile accessibile nella closure. Per esempio, per salvare il valore di una variabile al momento della creazione della closure:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Cattura initialValue per valore
currentValue += 1
print("Il valore iniziale era \(initialValue)") // initialValue mantiene il suo valore
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Output: Il valore iniziale era 5, poi 6
print(incrementer()) // Output: Il valore iniziale era 5, poi 7