Middle
Vorbește despre lista de captură în Swift.
sobes.tech AI
Răspuns de la AI
Lista de captură în Swift este utilizată pentru a gestiona explicit capturarea variabilelor de către closures. Acest lucru ajută la evitarea ciclurilor de referință puternice, mai ales atunci când lucrați cu self în closures utilizate în interiorul claselor. Tipurile principale de captură sunt: weak și unowned.
| Tip de captură | Descriere | Când să folosiți |
|---|---|---|
weak |
Capturează variabila ca opțional, fără a crește contorul de referințe. Valoarea sa poate deveni nil. |
Când obiectul closure-ului poate supraviețui obiectului capturat. |
unowned |
Capturează variabila fără a crește contorul de referințe, dar se presupune că obiectul capturat va trăi atât timp cât closure-ul există. Nu este opțional. | Când obiectul closure-ului și obiectul capturat au aceeași durată de viață, și obiectul capturat nu va fi nil înainte de finalizarea closure-ului. |
Sintaxa listei de captură:
{ [lista de captură] (parametri) -> tipDeReturn in
// cod
}
Exemplu de utilizare a weak self:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // verificare pentru nil
self.value += 1
print("Valoarea este acum \(self.value)")
}
}
}
Exemplu de utilizare a 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 nu este necesar în acest caz, deoarece butonul există atât timp cât ViewController-ul există.
// Dar dacă closure-ul ar putea supraviețui ViewController-ului, unowned ar fi potrivit dacă
// ești sigur că self nu va deveni nil.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Poți captura nu doar self, ci și orice alte variabile accesibile în closure. De exemplu, pentru a salva valoarea unei variabile în momentul creării closure-ului:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Capturează initialValue ca valoare
currentValue += 1
print("Valoarea inițială era \(initialValue)") // initialValue păstrează valoarea sa
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Output: Valoarea inițială era 5, apoi 6
print(incrementer()) // Output: Valoarea inițială era 5, apoi 7