Middle+
Ҳамеша бояд дар рӯйхати тасвиркунӣ weak ё unowned истифода шавад?
sobes.tech AI
Ҷавоб аз AI
Не, не винаги.
weak и unowned се използват за предотвратяване на силни цикли на препратки (retain cycles) в затварянията, когато затварянето държи силна препратка към обект, а обектът от своя страна държи силна препратка към затварянето.
weak или unowned трябва да се използват, когато затварянето улавя силна препратка към self или друг референтен тип и съществува вероятност да възникне силен цикъл.
Ситуации, когато не е необходимо да се използва weak/unowned:
- Затварянето улавя стойностни типове (структури, енумуей, кортежи). Те се копират при улавяне и не възникват цикли.
- Затварянето улавя референтен тип, но няма двупосочен силен цикъл. Например, ако затварянето се създава локално в метод и не се съхранява от обект, към който се отнася.
- Затварянето има кратък живот и ще бъде изпълнено преди обектът, към който се отнася, да бъде освободен. Например, затваряне, предадено като Completion Handler, което се изпълнява незабавно.
Избор между weak и unowned:
weak: използва се, когато уловеният обект може да станеnilпо всяко време преди изпълнението на затварянето. Препратката е като опционална (ObjectType?). Изисква се проверка заnilпреди използване.unowned: използва се, когато е известно, че уловеният обект винаги ще съществува по време на изпълнение на затварянето. Препратката не е опционална (ObjectType). Не изисква проверка заnil. Използването наunownedза обект, който е станалnil, ще доведе до срив (runtime error).
// Пример, когато не е необходим `weak`/`unowned` (улов на структура)
struct MyStruct {
var value: Int
}
let myStruct = MyStruct(value: 10)
let closure = {
print(myStruct.value) // копие на myStruct
}
closure()
// Пример, когато не е необходим `weak`/`unowned` (локално затваряне)
class MyClass {
func doSomething() {
let localValue = 5
let localClosure = {
print(self.description) // улов на self, но затварянето не се съхранява в MyClass
}
localClosure()
}
var description: String {
return "Instance of MyClass"
}
}
let myObject = MyClass()
myObject.doSomething()
// Пример, когато е необходим `weak` (може да стане `nil`)
class AsyncOperation {
var completionHandler: (() -> Void)?
func performOperation() {
DispatchQueue.global().async {
print("Operation completed")
self.completionHandler?()
}
}
deinit {
print("AsyncOperation deinitialized")
}
}
class ViewController {
var op: AsyncOperation?
func setupOperation() {
op = AsyncOperation()
op?.completionHandler = { [weak self] in
guard let self = self else { return }
print("Completion handler in ViewController: \(self)")
}
}
deinit {
print("ViewController deinitialized")
}
}
// Пример, когато е необходим `unowned` (гарантирано съществува)
class Button {
var action: (() -> Void)?
func tap() {
action?()
}
deinit {
print("Button deinitialized")
}
}
class ViewControllerWithButton {
var button: Button
init() {
button = Button()
button.action = { [unowned self] in
print("Button tapped in ViewControllerWithButton: \(self)")
}
}
deinit {
print("ViewControllerWithButton deinitialized")
}
}