Middle
Ispričaj o capture list u Swift-u.
sobes.tech АИ
Одговор од АИ
У Swift-у се користи capture list за јасно управљање хватањем променљивих у затворима (closures). Ово помаже у избегавању јаких циклуса референци, посебно када се ради са self унутар затвора који се користи у класама. Главне врсте хватања су: weak и unowned.
| Тип хватања | Опис | Када користити |
|---|---|---|
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