Sobes.tech
Middle

Papaskink apie capture sąrašą Swift.

sobes.tech AI

Atsakymas iš AI

Swift kalba capture list naudojama aiškiai valdyti užfiksuotų kintamųjų (closures) valdymą. Tai padeda išvengti stiprių nuorodų ciklų, ypač dirbant su self užfiksavimu uždarymuose, naudojamuose klasėse. Pagrindiniai užfiksavimo tipai: weak ir unowned.

Užfiksavimo tipas Aprašymas Kada naudoti
weak Užfiksuoja kintamąjį kaip pasirinktinį, nepadidindamas nuorodų skaitiklio. Jo reikšmė gali tapti nil. Kai užfiksuotas objektas gali išgyventi užfiksuotą objektą.
unowned Užfiksuoja kintamąjį be nuorodų skaitiklio didinimo, bet laikoma, kad užfiksuotas objektas gyvens tol, kol egzistuos uždarymas. Nėra pasirinktinė. Kai užfiksuotas objektas ir užfiksuojantis objektas turi tą patį gyvenimo laiką, ir užfiksuotas objektas nebus nil uždarymo pabaigoje.

Užfiksavimo sąrašo sintaksė:

{ [capture list] (parametrai) -> grąžinimo tipas in
    // kodas
}

Pavyzdys naudojant weak self:

class MyClass {
    var value = 0

    func doSomethingLater() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
            guard let self = self else { return } // Tikrinimas dėl `nil`
            self.value += 1
            print("Reikšmė dabar yra \(self.value)")
        }
    }
}

Pavyzdys naudojant 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 šiame pavyzdyje nereikalingas, nes mygtukas egzistuoja tol, kol egzistuoja ViewController.
        // Bet jei uždarymas galėtų išgyventi ViewController, unowned galėtų būti tinkamas, jei esame tikri,
        // kad self nebus `nil`.
        let action = { [unowned self] in
             self.view.backgroundColor = .blue
        }
        action()
    }
}

Užfiksuoti galima ne tik self, bet ir bet kurias kitas kintamąsias, kurios yra prieinamos uždaryme. Pavyzdžiui, norint išsaugoti kintamojo reikšmę uždarymo sukūrimo momentu:

func createIncrementer(initialValue: Int) -> () -> Int {
    var currentValue = initialValue
    return { [initialValue] in // Užfiksuojame initialValue pagal reikšmę
        currentValue += 1
        print("Pradinis reikšmė buvo \(initialValue)") // initialValue išsaugo savo reikšmę
        return currentValue
    }
}

let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Išvestis: Pradinis reikšmė buvo 5, tada 6
print(incrementer()) // Išvestis: Pradinis reikšmė buvo 5, tada 7