Middle
Mesélj a capture list-ről Swift-ben.
sobes.tech MI
Válasz az MI-től
A Swiftben a capture listet használják a változók explicit kezelésére a zárványok (closures) által történő elfogásakor. Ez segít elkerülni az erős ciklusokat, különösen akkor, amikor a self-et használják zárványokon belül, amelyek osztályokon belül vannak. A fő elfogási típusok: weak és unowned.
| Elfogási típus | Leírás | Mikor használjuk |
|---|---|---|
weak |
A változót opcionálisként fogja el, nem növelve a hivatkozásszámot. Az értéke nil lehet. |
Amikor az objektum, amit elfogunk, túléli az elfogott objektumot. |
unowned |
A változót anélkül fogja el, hogy növelné a hivatkozásszámot, de feltételezi, hogy az elfogott objektum életben marad, amíg a zárvány létezik. Nem opcionális. | Amikor a zárvány és az elfogott objektum élettartama megegyezik, és az elfogott objektum nem lesz nil a zárvány végéig. |
A capture list szintaxisa:
{ [capture list] (paraméterek) -> visszatérési típus in
// kód
}
Példa a weak self használatára:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // `nil` ellenőrzése
self.value += 1
print("Az érték most \(self.value)")
}
}
}
Példa az unowned self használatára:
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() {
// Az `unowned self` ebben az esetben nem szükséges, mivel a gomb létezik, amíg a ViewController is.
// De ha a zárvány túlélheti a ViewControllert, az `unowned` megfelelő lehet, ha biztosak vagyunk benne,
// hogy self nem lesz `nil`.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Nemcsak self-et, hanem más változókat is elfoghatunk, amelyek elérhetők a zárványban. Például, hogy megőrizzük egy változó értékét a zárvány létrehozásának pillanatában:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Az initialValue érték szerint fogja el
currentValue += 1
print("Az eredeti érték \(initialValue)") // Az initialValue megőrzi az eredeti értékét
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Kimenet: Az eredeti érték 5 volt, majd 6
print(incrementer()) // Kimenet: Az eredeti érték 5 volt, majd 7