Middle
Povedz mi o capture list v Swift-u.
sobes.tech AI
Odpoveď od AI
V Swift sa používa capture list na explicitnú správu zachytávania premenných v uzávierkach (closures). To pomáha vyhnúť sa silným cyklom odkazov, najmä pri práci s self vo vnútri uzávierok používaných v triedach. Hlavné typy zachytenia sú: weak a unowned.
| Typ zachytenia | Popis | Kedy použiť |
|---|---|---|
weak |
Zachytáva premennú ako voliteľnú, nezvyšuje počet odkazov. Jej hodnota môže byť nil. |
Keď objekt uzávierky môže prežiť zachytený objekt. |
unowned |
Zachytáva premennú bez zvýšenia počtu odkazov, ale predpokladá sa, že zachytený objekt bude žiť, kým existuje uzávierka. Nie je voliteľný. | Keď má uzávierka a zachytený objekt rovnakú dobu života a zachytený objekt nebude nil pred ukončením uzávierky. |
Syntax capture list:
{ [capture list] (parametre) -> návratový typ in
// kód
}
Príklad použitia 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 teraz \(self.value)")
}
}
}
Príklad použitia 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 nie je potrebné v tomto prípade, pretože button existuje, kým existuje ViewController.
// Ale ak by uzávierka mohla prežiť ViewController, unowned by mohol byť vhodný, ak sme si istí,
// že self nebude `nil`.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Zachytávať možno nielen self, ale aj akékoľvek iné premenné dostupné v uzávierke. Napríklad, aby ste zachovali hodnotu premennej v momente vytvorenia uzávierky:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Zachytávame initialValue podľa hodnoty
currentValue += 1
print("Počiatočná hodnota bola \(initialValue)") // initialValue si zachová svoju hodnotu
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Výstup: Počiatočná hodnota bola 5, potom 6
print(incrementer()) // Výstup: Počiatočná hodnota bola 5, potom 7