Vai vienmēr ir nepieciešams izmantot weak vai unowned Capture sarakstā?
sobes.tech AI
Atbilde no AI
Nē, ne vienmēr.
Mēs izmantojam weak vai unowned Capture List, lai novērstu retain cycle-us.
Retain cycle-i rodas, kad divi vai vairāki objekti stipri savienojas viens ar otru, neļaujot atbrīvot atmiņu.
weak vai unowned ir jāizmanto, ja slēptuve stipri saistās ar self (vai citu klases/aktorja mainīgo), un savukārt self (vai cits objekts) stipri saistās ar šo slēptuvi.
Piemēri situācijām, kur tas ir nepieciešams:
- Asinhroniskas operācijas (tīkla pieprasījumi, datu apstrāde)
- Observer modelis
- Animācijas bloki
- Dispatch rindas
Ja slēptuve neiekļauj self (vai citu klases/aktorja mainīgo, kam ir stipra saite uz slēptuvi), vai ietver strukturālus tipus vai sarakstus, weak vai unowned nav nepieciešams.
Atšķirība starp weak un unowned:
| Tips | Apraksts | Kad lietot |
|---|---|---|
weak |
Vājā (opcionālā) saite. Var kļūt par nil. |
Kad slēptuves dzīves cikls ir īsāks vai vienāds ar objekta dzīves ciklu, un objekts var kļūt par nil pirms slēptuves pabeigšanas. |
unowned |
Neatkarīga (opcionāla) saite. Nav iespējams kļūt par nil. |
Kad slēptuves dzīves cikls ir īsāks vai vienāds ar objekta dzīves ciklu, un ir garantija, ka objekts pastāvēs līdz slēptuves pabeigšanai. Ja objekts tiks atbrīvots pirms slēptuves izpildes, notiks kļūda (unowned saite uz atbrīvotu instance). |
weak piemērs:
class MyClass {
var name: String = "Test"
func performAsyncOperation() {
DispatchQueue.global().async { [weak self] in
guard let self = self else {
return
}
print("Darbība pabeigta \(self.name)")
}
}
deinit {
print("MyClass atbrīvots")
}
}
unowned piemērs:
class ViewController {
var dismissButton: UIButton!
func setupButton() {
dismissButton.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
// Šajā gadījumā, slēptuve saistās ar `self`.
// Ja tas būtu slēptuve, piemēram, UIControl.Event apstrādātājā,
// un ViewController pastāvēs ilgāk vai tikpat ilgi kā darbība:
// dismissButton.addAction(UIAction { [unowned self] _ in
// self.dismiss(animated: true, completion: nil)
// }, for: .touchUpInside)
}
@objc func dismiss() {
// Aizveriet skata kontrolieri
}
}
Ja slēptuve neveido retain cycle, weak vai unowned lietošana nav nepieciešama un pat var novest pie nevajadzīgām pārbaudēm (weak) vai potenciālām kļūdām (unowned).
Piemērs, kad slēptuve neiekļauj self vai citu objektu, kam ir stipra saite uz slēptuvi:
func fetchData(completion: @escaping (Data) -> Void) {
URLSession.shared.dataTask(with: URL(string: "...")!) { data, response, error in
guard let data = data else { return }
// Šeit nav `self` vai citu objektu, kas varētu radīt retain cycle.
completion(data)
}.resume()
}
Šajā gadījumā [weak self] vai [unowned self] nav nepieciešams.