Middle+
Da li je uvek potrebno koristiti weak ili unowned u Capture List?
sobes.tech АИ
Одговор од АИ
Не, не увек увек.
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 "Објекат MyClass"
}
}
let myObject = MyClass()
myObject.doSomething()
// Пример, када је потребан `weak` (може бити `nil`)
class AsyncOperation {
var completionHandler: (() -> Void)?
func performOperation() {
DispatchQueue.global().async {
print("Операција завршена")
self.completionHandler?()
}
}
deinit {
print("AsyncOperation је ослобођен")
}
}
class ViewController {
var op: AsyncOperation?
func setupOperation() {
op = AsyncOperation()
op?.completionHandler = { [weak self] in
guard let self = self else { return }
print("Завршни руковаоци у ViewController-у: \(self)")
}
}
deinit {
print("ViewController је ослобођен")
}
}
// Пример, када је потребан `unowned` (гарантовано постоји)
class Button {
var action: (() -> Void)?
func tap() {
action?()
}
deinit {
print("Button је ослобођен")
}
}
class ViewControllerWithButton {
var button: Button
init() {
button = Button()
button.action = { [unowned self] in
print("Тастер је притиснут у ViewControllerWithButton-у: \(self)")
}
}
deinit {
print("ViewControllerWithButton је ослобођен")
}
}