Sobes.tech
Middle

Räägi mulle capture listist Swiftis.

sobes.tech AI

Vastus AI-lt

Swiftis kasutatakse capture listi, et selgelt hallata muutujate haaramist suletistes (closures). See aitab vältida tugevaid viidetsüklusi, eriti kui kasutatakse self-i suletistes, mis on kasutusel klassides. Peamised haaratüübid on: weak ja unowned.

Haaratüüp Kirjeldus Millal kasutada
weak Haarab muutuja valikulisena, mitte suurendades viidete arvu. Selle väärtus võib muutuda nil-iks. Kui haaratud objekt võib elada üle haaratud objekti.
unowned Haarab muutuja ilma viidete arvu suurendamata, eeldades, et haaratud objekt elab seni, kuni suletis eksisteerib. Ei ole valikuline. Kui suletis ja haaratud objekt on sama eluea ning haaratud objekt ei muutu nil-iks suletise lõpuks.

Capture listi süntaks:

{ [capture list] (parameetrid) -> tagastatüüp in
    // kood
}

Näide weak self kasutamisest:

class MyClass {
    var value = 0

    func doSomethingLater() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
            guard let self = self else { return } // `nil` kontroll
            self.value += 1
            print("Väärtus on nüüd \(self.value)")
        }
    }
}

Näide unowned self kasutamisest:

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 ei ole selles olukorras vajalik, kuna nupp eksisteerib seni, kuni eksisteerib ViewController.
        // Kui suletis võiks elada üle ViewControlleri, siis unowned oleks sobiv, kui oleme kindlad,
        // et self ei muutu `nil`-iks.
        let action = { [unowned self] in
             self.view.backgroundColor = .blue
        }
        action()
    }
}

Haarata võib mitte ainult self, vaid ka teisi muutujaid, mis on suletises kättesaadavad. Näiteks, et salvestada muutuja väärtus selle loomise hetkel:

func createIncrementer(initialValue: Int) -> () -> Int {
    var currentValue = initialValue
    return { [initialValue] in // Haarame initialValue väärtuse järgi
        currentValue += 1
        print("Algväärtus oli \(initialValue)") // initialValue säilitab oma väärtuse
        return currentValue
    }
}

let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Väljund: Algväärtus oli 5, siis 6
print(incrementer()) // Väljund: Algväärtus oli 5, siis 7