Middle
Pověz mi o seznamu zachycení v Swift.
sobes.tech AI
Odpověď od AI
V Swiftu se používá capture list pro explicitní správu zachycení proměnných uzávěry (closures). To pomáhá zabránit silným cyklům odkazů, zejména při práci s self uvnitř uzávěrů používaných ve třídách. Hlavní typy zachycení: weak a unowned.
| Typ zachycení | Popis | Kdy použít |
|---|---|---|
weak |
Zachytí proměnnou jako volitelnou, nezvyšuje počítadlo odkazů. Její hodnota může být nil. |
Když objekt uzávěru může přežít zachycený objekt. |
unowned |
Zachytí proměnnou bez zvýšení počítadla odkazů, ale předpokládá se, že zachycený objekt bude žít, dokud existuje uzávěr. Není volitelný. | Když mají uzávěr a zachycený objekt stejnou dobu života a zachycený objekt nebude nil do ukončení uzávěru. |
Syntaxe capture list:
{ [capture list] (parametry) -> návratový typ in
// kód
}
Příklad použití weak self:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // Kontrola na nil
self.value += 1
print("Hodnota je nyní \(self.value)")
}
}
}
Příklad použití 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 není v tomto případě potřeba, protože button existuje, dokud existuje ViewController.
// Ale pokud by uzávěr mohl přežít ViewController, mohl by být vhodný unowned, pokud si jsme jisti,
// že self nebude `nil`.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Zachytit lze nejen self, ale i jiné proměnné dostupné v uzávěru. Například, aby se zachovala hodnota proměnné v okamžiku vytvoření uzávěru:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Zachytíme initialValue podle hodnoty
currentValue += 1
print("Původní hodnota byla \(initialValue)") // initialValue si zachová svou hodnotu
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Výstup: Původní hodnota byla 5, pak 6
print(incrementer()) // Výstup: Původní hodnota byla 5, pak 7