Sobes.tech
Middle

Vorbește despre lista de captură în Swift.

sobes.tech AI

Răspuns de la AI

Lista de captură în Swift este utilizată pentru a gestiona explicit capturarea variabilelor de către closures. Acest lucru ajută la evitarea ciclurilor de referință puternice, mai ales atunci când lucrați cu self în closures utilizate în interiorul claselor. Tipurile principale de captură sunt: weak și unowned.

Tip de captură Descriere Când să folosiți
weak Capturează variabila ca opțional, fără a crește contorul de referințe. Valoarea sa poate deveni nil. Când obiectul closure-ului poate supraviețui obiectului capturat.
unowned Capturează variabila fără a crește contorul de referințe, dar se presupune că obiectul capturat va trăi atât timp cât closure-ul există. Nu este opțional. Când obiectul closure-ului și obiectul capturat au aceeași durată de viață, și obiectul capturat nu va fi nil înainte de finalizarea closure-ului.

Sintaxa listei de captură:

{ [lista de captură] (parametri) -> tipDeReturn in
    // cod
}

Exemplu de utilizare a weak self:

class MyClass {
    var value = 0

    func doSomethingLater() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
            guard let self = self else { return } // verificare pentru nil
            self.value += 1
            print("Valoarea este acum \(self.value)")
        }
    }
}

Exemplu de utilizare a 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 nu este necesar în acest caz, deoarece butonul există atât timp cât ViewController-ul există.
        // Dar dacă closure-ul ar putea supraviețui ViewController-ului, unowned ar fi potrivit dacă
        // ești sigur că self nu va deveni nil.
        let action = { [unowned self] in
             self.view.backgroundColor = .blue
        }
        action()
    }
}

Poți captura nu doar self, ci și orice alte variabile accesibile în closure. De exemplu, pentru a salva valoarea unei variabile în momentul creării closure-ului:

func createIncrementer(initialValue: Int) -> () -> Int {
    var currentValue = initialValue
    return { [initialValue] in // Capturează initialValue ca valoare
        currentValue += 1
        print("Valoarea inițială era \(initialValue)") // initialValue păstrează valoarea sa
        return currentValue
    }
}

let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Output: Valoarea inițială era 5, apoi 6
print(incrementer()) // Output: Valoarea inițială era 5, apoi 7