Mindig szükséges weak vagy unowned használata a Capture List-ben?
sobes.tech MI
Válasz az MI-től
Nem, nem mindig.
A weak vagy unowned használata a Capture List-ben a retain ciklusok megelőzése érdekében.
A retain ciklus akkor fordul elő, amikor két vagy több objektum erősen hivatkozik egymásra, megakadályozva a memória felszabadítását.
A weak vagy unowned akkor szükséges, ha egy záradék erősen hivatkozik self-re (vagy más példányváltozóra az osztályban/aktorban), és viszont self (vagy más objektum) erős hivatkozással rendelkezik erre a záradékra.
Példák, amikor ez szükséges:
- Aszinkron műveletek (hálózati kérések, adatok feldolgozása)
- Observer mintázat
- Animációs blokkok
- Dispatch sorok
Ha a záradék nem foglalja el self-t (vagy más osztály/aktor változót, amely erős hivatkozással rendelkezik a záradékra), vagy strukturális típusokat/enumerációkat foglal magában, akkor a weak vagy unowned használata nem szükséges.
A weak és unowned közötti különbség:
| Típus | Leírás | Mikor használjuk |
|---|---|---|
weak |
Gyenge (opcionális) hivatkozás. nil lehet. |
Amikor a záradék életciklusa rövidebb vagy egyenlő a fogott objektum életciklusával, és az objektum nil lehet a záradék befejezése előtt. |
unowned |
Nem fő (nem opcionális) hivatkozás. Nem lehet nil. |
Amikor a záradék életciklusa rövidebb vagy egyenlő a fogott objektum életciklusával, és garantált, hogy az objektum a záradék befejezése előtt létezik. Ha az objektum megszűnik a záradék végrehajtása előtt, akkor hibát okoz (unowned referencia a felszabadított példányra). |
Példa a weak használatára a Capture List-ben:
class MyClass {
var name: String = "Test"
func performAsyncOperation() {
DispatchQueue.global().async { [weak self] in
guard let self = self else {
return
}
print("Művelet befejeződött: \(self.name)")
}
}
deinit {
print("MyClass felszabadult")
}
}
Példa az unowned használatára a Capture List-ben:
class ViewController {
var dismissButton: UIButton!
func setupButton() {
dismissButton.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
// Ez a példa azt mutatja, hogy a `self` (ViewController) hosszabb vagy ugyanannyi ideig él, mint a gomb művelete.
// A target-action nem záradék, de illusztrálja az unowned koncepciót erős hivatkozási ciklus esetén.
// Ha ez záradék lenne, például UIControl.Event kezelőben,
// és a ViewController garantáltan létezik a gomb megnyomásakor:
// dismissButton.addAction(UIAction { [unowned self] _ in
// self.dismiss(animated: true, completion: nil)
// }, for: .touchUpInside)
}
@objc func dismiss() {
// Nézetvezérlő elvetése
}
}
Ha a záradék nem hoz létre retain ciklust, a weak vagy unowned használata nem kötelező, és akár szükségtelen ellenőrzésekhez (a weak esetén) vagy potenciális hibákhoz (az unowned esetén) vezethet.
Például egy záradék, amely nem foglalja el self-t vagy más objektumot, amely erős hivatkozással rendelkezik a záradékra:
func fetchData(completion: @escaping (Data) -> Void) {
URLSession.shared.dataTask(with: URL(string: "...")!) { data, response, error in
guard let data = data else { return }
// Itt nincs foglalás `self`-re vagy más objektumokra, amelyek ciklust okozhatnak.
completion(data)
}.resume()
}
Ebben az esetben [weak self] vagy [unowned self] a Capture List-ben nem szükséges.