Ամեն դեպքում անհրաժեշտ է օգտագործել weak կամ unowned բռնագրավման ցանկում:
sobes.tech AI
Պատասխան AI-ից
Ոչ, ոչ միշտ։
Օգտագործում ենք weak կամ unowned Capture List-ում՝ կանխելու համար retain cycle-երը։
Retain cycle-երը առաջանում են, երբ երկու կամ ավելի օբյեկտներ ուժեղորեն հղում են միմյանց, ինչը չի թույլատրում հիշողությունը ազատել։
Օգտագործել weak կամ unowned անհրաժեշտ է, երբ կարճաժամկետ փակումը ուժեղորեն հղում է self (կամ այլ դասի/ակտորի օրինակային փոփոխական), և իր հերթին self (կամ այլ օբյեկտ) ունի ուժեղ հղում այդ փակմանը։
Նմուշներ իրավիճակների, երբ դա անհրաժեշտ է՝
- Ասինխրոն օպերացիաներ (սնետվերային հարցումներ, տվյալների մշակում)
- Observer պաթերն
- Անիմացիոն բլոկներ
- Dispatch հերթեր
Եթե փակումը չի բռնում self-ին (կամ այլ դասի/ակտորի փոփոխական, որը ունի ուժեղ հղում փակմանը), կամ բռնում է կառուցվածքային տիպեր/համարներ, weak կամ unowned օգտագործելը անհրաժեշտ չէ։
weak և unowned միջև տարբերությունը՝
| Տիպ | Նկարագրություն | Երբ օգտագործել |
|---|---|---|
weak |
Թույլ (ընտրական) հղում։ Կարող է դառնալ nil։ |
Երբ փակման կյանքի ցիկլը կարճ է կամ հավասար է բռնված օբյեկտի կյանքի ցիկլին, և օբյեկտը կարող է դառնալ nil մինչև փակման ավարտը։ |
unowned |
Անվճար (չընտրական) հղում։ Չի կարող դառնալ nil։ |
Երբ փակման կյանքի ցիկլը կարճ է կամ հավասար է բռնված օբյեկտի կյանքի ցիկլին, և հաստատապես հստակ է, որ օբյեկտը գոյություն կունենա մինչև փակման ավարտը։ Եթե օբյեկտը ազատվի մինչև փակման կատարմանը, տեղի կունենա խափանում (unowned հղում deallocated instance-ին): |
Օրինակ weak օգտագործման՝
class MyClass {
var name: String = "Test"
func performAsyncOperation() {
DispatchQueue.global().async { [weak self] in
guard let self = self else {
return
}
print("Operation completed for \(self.name)")
}
}
deinit {
print("MyClass deallocated")
}
}
Օրինակ unowned օգտագործման՝
class ViewController {
var dismissButton: UIButton!
func setupButton() {
dismissButton.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
// Այս դեպքում, փակումը բռնում է `self`-ին։
// Եթե դա լիներ փակում, օրինակ, UIControl.Event-ի մշակողում,
// և ViewController-ը հաստատ գոյություն կունենա մինչև կոճակի սեղմումը՝
// dismissButton.addAction(UIAction { [unowned self] _ in
// self.dismiss(animated: true, completion: nil)
// }, for: .touchUpInside)
}
@objc func dismiss() {
// Դիսմիս տեսքի կառավարման համար
}
}
Եթե փակումը չի ստեղծում retain cycle, weak կամ unowned օգտագործելը անհրաժեշտ չէ և նույնիսկ կարող է հանգեցնել ավելորդ ստուգումների (կամ weak-ի դեպքում) կամ հնարավոր խափանումների (կամ unowned-ի դեպքում):
Օրինակ՝ փակումը, որը չի բռնում self-ին կամ այլ օբյեկտ, որի ուժեղ հղումը կա փակման մեջ՝
func fetchData(completion: @escaping (Data) -> Void) {
URLSession.shared.dataTask(with: URL(string: "...")!) { data, response, error in
guard let data = data else { return }
// Այստեղ չկա `self` կամ այլ օբյեկտների բռնում, որոնք կարող են առաջացնել retain cycle։
completion(data)
}.resume()
}
Այս դեպքում [weak self] կամ [unowned self] օգտագործելը անհրաժեշտ չէ։