Middle
Erzählen Sie mir von der Capture-Liste in Swift.
sobes.tech KI
Antwort von AI
Die Capture-Liste in Swift wird verwendet, um die explizite Steuerung der Variablenaufnahme durch Closures zu ermöglichen. Dies hilft, starke Referenzzyklen zu vermeiden, insbesondere bei der Arbeit mit self in Closures, die innerhalb von Klassen verwendet werden. Die Haupttypen der Aufnahme sind: weak und unowned.
| Aufnahme-Typ | Beschreibung | Wann verwenden |
|---|---|---|
weak |
Nimmt die Variable als Optional auf, ohne den Referenzzähler zu erhöhen. Ihr Wert kann nil werden. |
Wenn das Objekt des Closures das gecapturierte Objekt überleben kann. |
unowned |
Nimmt die Variable ohne Erhöhung des Referenzzählers auf, wird aber angenommen, dass das gecapturierte Objekt lebt, solange das Closure existiert. Nicht optional. | Wenn das Objekt des Closures und das gecapturierte Objekt die gleiche Lebensdauer haben und das gecapturierte Objekt vor Abschluss des Closures nicht nil wird. |
Syntax der Capture-Liste:
{ [capture list] (Parameter) -> Rückgabetyp in
// Code
}
Beispiel für die Verwendung von weak self:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // nil-Check
self.value += 1
print("Wert ist jetzt \(self.value)")
}
}
}
Beispiel für die Verwendung von 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 ist in diesem Fall nicht erforderlich, da der Button so lange existiert, wie der ViewController.
// Wenn das Closure den ViewController überleben könnte, wäre unowned angemessen, wenn
// man sicher ist, dass self nicht `nil` wird.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Es können nicht nur self, sondern auch andere Variablen, die im Closure zugänglich sind, gecaptur werden. Zum Beispiel, um den Wert einer Variablen zum Zeitpunkt der Erstellung des Closures zu speichern:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // initialValue wird per Wert gecaptur
currentValue += 1
print("Initialer Wert war \(initialValue)") // initialValue behält seinen Wert
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Ausgabe: Initialer Wert war 5, dann 6
print(incrementer()) // Ausgabe: Initialer Wert war 5, dann 7