Middle
Faut-il toujours spécifier le paramètre `self` dans les closures?
sobes.tech IA
Réponse de l'IA
Non, pas toujours.
Il est nécessaire d’indiquer explicitement self dans les closures uniquement dans les cas suivants :
- Dans les closures non échappants (non-escaping) : C’est une exigence du compilateur pour marquer explicitement la capture de
self. Bien qu’il y ait une capture techniquement, elle se produit à l’intérieur de la fonction et ne conduit pas à des cycles de références fortes. - Dans les closures échappants (escaping) lors de la capture de
selfpar défaut (capture implicite) : Si la closure sort du contexte de la fonction dans laquelle elle a été déclarée (par exemple, elle est transmise à une opération asynchrone, stockée dans une propriété, etc.), et que vous capturezselfde manière implicite, le compilateur exigera que vous indiquiez explicitementselfpour plus de clarté concernant d’éventuels cycles de références fortes.
Dans d’autres cas (par exemple, dans les closures échappants utilisant la liste de capture [weak self] ou [unowned self]), il n’est pas nécessaire d’indiquer self, car la relation de propriété est contrôlée explicitement.
Exemple :
class MyClass {
var value = 10
func doSomething() {
// Closure non échappante - nécessite `self`
UIView.animate(withDuration: 0.3) {
self.value = 20
}
}
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Closure échappante avec capture implicite de `self` - nécessite `self`
// Peut conduire à un cycle de références fortes si `[weak self]` n’est pas utilisé
someAsyncOperation { data, error in
if let data = data {
// Nécessite `self` lors de l’utilisation de la capture implicite
self.processData(data)
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
func safelyFetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Closure échappante avec capture explicite `[weak self]` - `self?` est optionnel et ne nécessite pas `self.` explicite
someAsyncOperation { [weak self] data, error in
guard let self = self else { return } // Déballer `self` optionnel
if let data = data {
self.processData(data) // Pas besoin de `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) {
// Simulation d’une opération asynchrone
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("Some data", nil)
}
}