Middle
Vždy je potrebné uvádzať parameter `self` v uzávierkach?
sobes.tech AI
Odpoveď od AI
Nie, nie vždy.
Je potrebné jasne uviesť self v uzávierkach iba v nasledujúcich prípadoch:
- V ne-unikajúcich (non-escaping) uzávierkach: Ide o požiadavku kompilátora na jasné označenie zachytenia
self. Hoci zachytenie technicky existuje, prebieha vo vnútri funkcie a nevytvára cykly silných odkazov. - V unikajúcich (escaping) uzávierkach pri zachytení
selfimplicitne (implicit capture): Ak uzávierka presahuje rámec funkcie, v ktorej bola deklarovaná (napríklad, je odovzdávaná do asynchrónnej operácie, je uložená do vlastnosti atď.), a zachytávateselfneexplicitne, kompilátor bude požadovať explicitné uvedenieselfpre prehľadnosť potenciálneho cyklu silných odkazov.
Vo všetkých ostatných prípadoch (napríklad, v unikajúcich uzávierkach pri použití zoznamu zachytenia [weak self] alebo [unowned self]) nie je potrebné uvádzať self, pretože vzťah vlastníctva je explicitne riadený.
Príklad:
class MyClass {
var value = 10
func doSomething() {
// Neunikajúca uzávierka - je požadované `self`
UIView.animate(withDuration: 0.3) {
self.value = 20
}
}
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Unikajúca uzávierka s neexplicitným zachytením `self` - je požadované `self`
// Môže viesť k potenciálnemu cyklu silných odkazov, ak sa nepoužije `[weak self]`
someAsyncOperation { data, error in
if let data = data {
// Vyžaduje `self` pri použití neexplicitného zachytenia
self.processData(data)
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
func bezpečneFetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Unikajúca uzávierka s explicitným zachytením `[weak self]` - `self?` je voliteľný a nevyžaduje explicitné `self.` pred volaním
someAsyncOperation { [weak self] data, error in
guard let self = self else { return } // Rozbalenie `self` ako voliteľného
if let data = data {
self.processData(data) // Nie je potrebné `self.`
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
private func processData(_ data: String) {
print("Processing \(data)")
}
}
func someAsyncOperation(completion: @escaping (String?, Error?) -> Void) {
// Imaginárna asynchrónna operácia
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("Some data", nil)
}
}