Middle+
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 és az unowned a gyenge hivatkozási ciklusok (retain cycles) megelőzésére szolgálnak a záradékokban, ahol a záradék erős hivatkozást tart fenn egy objektumra, és az objektum viszont erős hivatkozást tart fenn a záradékra.
A weak vagy unowned használata szükséges, ha a záradék erős hivatkozást tart fenn self-re vagy más referenciális típusra, és fennáll a gyenge hivatkozási ciklus kialakulásának lehetősége.
Olyan helyzetek, amikor nem kell weak/unowned:
- A záradék értéktípusokat (struktúrák, felsorolások, tuple-k) tart fenn. Ezek másolatként kerülnek átadásra, és nem alakulnak ki ciklusok.
- A záradék referenciatípust tart fenn, de kétirányú erős hivatkozás nem létezik. Például, ha a záradék helyileg jön létre egy metódusban, és nem tárolja egy objektum.
- A záradék rövid életű, és a rá hivatkozó objektum felszabadítása előtt végrehajtódik. Például, ha a záradék egy metódusban átadott Completion Handler, amely azonnal végrehajtódik.
A weak és unowned közötti választás:
weak: akkor használjuk, ha az igevett objektum bármikornil-vé válhat a záradék végrehajtása előtt. Az hivatkozás opcionális (ObjectType?).nilellenőrzése szükséges a használat előtt.unowned: akkor használjuk, ha tudjuk, hogy az igevett objektum mindig létezik a záradék végrehajtásakor. Az hivatkozás nem opcionális (ObjectType).nilellenőrzése nem szükséges. Azunownedhasználata olyan objektum esetén, amelynil-vé válik, runtime hibát eredményez.
// Példa, amikor nincs szükség `weak`/`unowned`-re (struktúra igevitel)
struct MyStruct {
var value: Int
}
let myStruct = MyStruct(value: 10)
let closure = {
print(myStruct.value) // másolatot vesz a myStruct-ről
}
closure()
// Példa, amikor nincs szükség `weak`/`unowned`-re (helyi záradék)
class MyClass {
func doSomething() {
let localValue = 5
let localClosure = {
print(self.description) // self-t igevéli, de a záradék nem tárolódik a MyClass-ben
}
localClosure()
}
var description: String {
return "MyClass példány"
}
}
let myObject = MyClass()
myObject.doSomething()
// Példa, amikor `weak` szükséges (esetleg `nil`)
class AsyncOperation {
var completionHandler: (() -> Void)?
func performOperation() {
DispatchQueue.global().async {
print("Művelet befejeződött")
self.completionHandler?()
}
}
deinit {
print("AsyncOperation felszabadult")
}
}
class ViewController {
var op: AsyncOperation?
func setupOperation() {
op = AsyncOperation()
op?.completionHandler = { [weak self] in
guard let self = self else { return }
print("Completion handler a ViewController-ben: \(self)")
}
}
deinit {
print("ViewController felszabadult")
}
}
// Példa, amikor `unowned` szükséges (biztosan létezik)
class Button {
var action: (() -> Void)?
func tap() {
action?()
}
deinit {
print("Button felszabadult")
}
}
class ViewControllerWithButton {
var button: Button
init() {
button = Button()
button.action = { [unowned self] in
print("Gomb megnyomva a ViewControllerWithButton-ben: \(self)")
}
}
deinit {
print("ViewControllerWithButton felszabadult")
}
}