Sobes.tech
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