Middle
պատմիր Swift-ում capture ցուցակի մասին։
sobes.tech AI
Պատասխան AI-ից
Swift- ում capture list-ը օգտագործվում է փոփոխականների բացահայտ կառավարման համար փակագծերում (closures): Սա օգնում է խուսափել ուժեղ ռեֆերենցիայի ցիկլերից, հատկապես այն ժամանակ, երբ օգտագործվում է self փակագծերի ներսում, որոնք օգտագործվում են դասարաններում: Հիմնական capture տեսակները՝ weak և unowned են:
| Capture տեսակ | Նկարագրություն | Երբ օգտագործել |
|---|---|---|
weak |
Հավաքում է փոփոխականը որպես ընտրանքային, առանց ռեֆերենցիայի հաշվիչը բարձրացնելու: Նրա արժեքը կարող է դառնալ nil: |
Երբ օբյեկտը փակագծի կարող է գոյատևել բռնված օբյեկտից: |
unowned |
Հավաքում է փոփոխականը առանց ռեֆերենցիայի հաշվիչը բարձրացնելու, բայց ենթադրվում է, որ բռնված օբյեկտը կշարունակի գոյատևել, մինչեւ փակագծի ավարտը: Չի լինել ընտրանքային: | Երբ փակագիծը եւ բռնված օբյեկտը ունեն նույն կյանքի ժամկետը, եւ բռնված օբյեկտը nil չի դառնա մինչեւ փակագծի ավարտը: |
Capture list-ի սինտաքսիս:
{ [capture list] (պարամետրեր) -> վերադարձվող տեսակ in
// կոդ
}
Օրինակ՝ weak self օգտագործելու համար:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // `nil` ստուգում
self.value += 1
print("Արժեքը այժմ \(self.value)")
}
}
}
Օրինակ՝ unowned self օգտագործելու համար:
class ViewController: UIViewController {
var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button = UIButton(type: .system)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}
@objc func buttonTapped() {
// unowned self այս դեպքում անհրաժեշտ չէ, քանի որ բիթոնը գոյություն ունի, քանի դեռ կա ViewController-ը:
// Բայց եթե փակագիծը կարող է գոյատևել ViewController-ից, unowned-ը կարող է լինել տեղին, եթե վստահ ենք,
// որ self-ը `nil` չի դառնա:
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Անհրաժեշտ է, որ ոչ միայն self-ը, այլ նաև այլ փոփոխականներ, որոնք հասանելի են փակագծում, բռնվեն: Օրինակ՝ փոփոխականի արժեքը պահելու համար այն պահին, երբ ստեղծվում է փակագիծը:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // բռնում ենք initialValue արժեքով
currentValue += 1
print("Առաջին արժեքը եղել է \(initialValue)") // initialValue պահում է իր արժեքը
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Արտածում՝ Առաջին արժեքը եղել է 5, հետո 6
print(incrementer()) // Արտածում՝ Առաջին արժեքը եղել է 5, հետո 7