Middle
Kas on alati vaja märkida `self` parameeter sulgemistes?
sobes.tech AI
Vastus AI-lt
Ei, mitte alati.
On vaja selgelt märkida self sulgudes ainult järgmistes juhtudel:
- Mitte-escape (non-escaping) sulgudes: See on kompilaatori nõue selgelt märkida
selfhaaramine. Kuigi haaramine on tehniliselt olemas, toimub see funktsiooni sees ega põhjusta tugevaid viiditsüklisid. - Escape (väljuvad) sulgudes, kui
selfhaaramine on vaikimisi (implicit capture): Kui sulg väljub funktsiooni piiridest, kus see oli deklareeritud (näiteks edastatakse asünkroonsele operatsioonile, salvestatakse omadusse jms), ja te haarateself-i ebamääraselt, nõuab kompilaator selgetselfmärkust, et vältida potentsiaalseid tugevaid viiditsüklisid.
Kõik teised juhtumid (näiteks [weak self] või [unowned self] loeteluga) ei nõua self märkust, kuna omandi suhe on selgelt kontrollitud.
Näide:
class MyClass {
var value = 10
func doSomething() {
// Mitte-escape sulg - nõutud `self`
UIView.animate(withDuration: 0.3) {
self.value = 20
}
}
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Escape sulg ebamäärase `self` haaramisega - nõutud `self`
// Võib põhjustada tugeva viiditsüklilise olukorra, kui `[weak self]` ei kasutata
someAsyncOperation { data, error in
if let data = data {
// Nõutud `self` ebamäärase haaramise korral
self.processData(data)
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
func turvaliseltFetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Escape sulg koos `[weak self]`-ga - `self?` on valikuline ja ei nõua `self.`-i enne kasutamist
someAsyncOperation { [weak self] data, error in
guard let self = self else { return } // Lahtivõtmine `self` valikulise
if let data = data {
self.processData(data) // Ei ole vaja `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) {
// Asünkroonne operatsioon
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("Some data", nil)
}
}