Middle
Je vždy třeba uvádět parametr `self` v uzávěrkách?
sobes.tech AI
Odpověď od AI
Ne, ne vždy.
Je nutné explicitně uvádět self v uzávěrech pouze v následujících případech:
- V ne-unikajících (non-escaping) uzávěrech: Jedná se o požadavek kompilátoru na jasné označení zachycení
self. Ačkoliv zachycení technicky existuje, probíhá uvnitř funkce a nevytváří cykly silných odkazů. - V unikajících (escaping) uzávěrech při zachycení
selfimplicitně (implicit capture): Pokud uzávěr přesahuje rámec funkce, ve které byl deklarován (například je předáván do asynchronní operace, je uložen do vlastnosti atd.), a zachytáváteselfneexplicitně, kompilátor bude požadovat explicitní uvedeníselfpro přehlednost potenciálního cyklu silných odkazů.
Ve všech ostatních případech (například v unikajících uzávěrech při použití seznamu zachycení [weak self] nebo [unowned self]) není nutné uvádět self, protože vztah vlastnictví je explicitně řízen.
Příklad:
class MyClass {
var value = 10
func doSomething() {
// Neunikající uzávěr - je požadováno `self`
UIView.animate(withDuration: 0.3) {
self.value = 20
}
}
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Unikající uzávěr s neexplicitním zachycením `self` - je požadováno `self`
// Může vést k potenciálnímu cyklu silných odkazů, pokud se nepoužije `[weak self]`
someAsyncOperation { data, error in
if let data = data {
// Vyžaduje `self` při použití neexplicitního zachycení
self.processData(data)
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
func safelyFetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Unikající uzávěr s explicitním zachycením `[weak self]` - `self?` je volitelný a nevyžaduje explicitní `self.` před voláním
someAsyncOperation { [weak self] data, error in
guard let self = self else { return } // Rozbalení `self` jako volitelného
if let data = data {
self.processData(data) // `self.` není nutné
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) {
// Simulace asynchronní operace
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("Some data", nil)
}
}