Какво е затваряне?
sobes.tech AI
Отговор от AI
Затваряне (closure) в Swift е самодостатъчен блок от функционалност ({}), който може да бъде предаден и използван в кода. Затварянията могат да захващат и съхраняват препратки към всякакви константи и променливи от контекста, в който са дефинирани.
Примери за използване:
- Като аргументи на функции (например, Completion Handlers).
- За определяне на поведение при обхождане на колекции (например, използвайки методите
map,filter,reduce,sorted). - За отложено изпълнение на код.
Синтаксис:
// Основен синтаксис
{ (параметри) -> типНаВръщане in
изрази
}
// Пример за затваряне, което приема Int и връща String
let integerToString: (Int) -> String = { (number: Int) -> String in
return "Число: \(number)"
}
Особености:
- Автоматично захващане на променливи (capturing values).
- Възможност за дефиниране на затваряния без явно указване на типове на параметрите и връщаната стойност (синтактичен захар).
- Използване на съкратени имена на параметри ($0, $1 и т.н.).
- Синтаксис на затварящия блок (trailing closure syntax).
Захващане на променливи:
Затварянето може да захване променливи от своята среда. По подразбиране захващането става по препратка. Ако затварянето се използва след като оригиналната променлива е излязла от обхвата си, затварянето все още запазва достъп до нея.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0 // Променлива от външния контекст
let incrementer: () -> Int = { // Затваряне
runningTotal += amount // Захваща runningTotal и amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // Изход: 10
print(incrementByTen()) // Изход: 20
Списъци за захващане (Capture Lists):
Използват се за явно указване как трябва да бъдат захванати променливите - по стойност или по препратка, както и за избягване на силни цикли на препратки (retain cycles).
class MyClass {
var value = 0
lazy var myClosure: () -> Void = { [self, value] in // Захващане на self по препратка, а value по стойност
print("Стойност на self.value: \(self.value)")
print("Захваната стойност: \(value)")
}
deinit {
print("Обектът MyClass е освободен")
}
}
За предотвратяване на силни цикли при захващане на обекти от класове се използва синтаксисът [weak self] или [unowned self].
class ViewController {
var dataFetcher: DataFetcher?
func fetchData() {
dataFetcher?.fetch { [weak self] result in // слабо захващане на self
guard let self = self else { return } // проверка за съществуване на self
// обработка на резултата
}
}
}
class DataFetcher {
var completionHandler: ((Result<String, Error>) -> Void)?
func fetch(completion: @escaping (Result<String, Error>) -> Void) {
self.completionHandler = completion
// Асимхронна операция...
}
}