Middle
Yopiq funksiyalarda har doim `self` parametrini ko'rsatish kerakmi?
sobes.tech AI
AIdan javob
Xeyr, hər zaman deyil.
self'in açıq şəkildə göstərilməsi yalnız aşağıdakı hallarda tələb olunur:
- Qayıtmayacaq (non-escaping) bağlamalarda: Bu, tərtibçi tərəfindən
self-in ələ keçirilməsini açıq şəkildə qeyd etmək üçün tələb olunur. Texniki olaraq, ələ keçirilmə mövcuddur, lakin bu, funksiyanın daxilində baş verir və güclü referans döngələrinə səbəb olmur. - Qaçan (escaping) bağlamalarda,
self-in varsayılan (örtük) ələ keçirilməsi: Əgər bağlama, elan olunduğu funksiyanın sərhədindən çıxırsa (məsələn, asinxron əməliyyata ötürülür, xüsusiyyətə saxlanılır və s.), vəself-i qeyri-şəffaf şəkildə ələ keçirirsinizsə, tərtibçi potensial güclü referans döngələrini aydınlaşdırmaq üçünself-i açıq şəkildə göstərməyinizi tələb edəcək.
Digər hallarda (məsələn, [weak self] və ya [unowned self] istifadə edilən qaçan bağlamalarda), self-i göstərmək lazım deyil, çünki mülkiyyət münasibətləri açıq şəkildə idarə olunur.
Nümunə:
class MyClass {
var value = 10
func doSomething() {
// Qayıtmayacaq bağlama - `self` tələb olunur
UIView.animate(withDuration: 0.3) {
self.value = 20
}
}
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Qaçan bağlama, qeyri-şəffaf `self` ələ keçirilməsi - `self` tələb olunur
// `[weak self]` istifadə edilməzsə, güclü referans döngüsü ilə nəticələnə bilər
someAsyncOperation { data, error in
if let data = data {
// Qeyri-şəffaf ələ keçirilmə zamanı `self` tələb olunur
self.processData(data)
completion(.success("Data processed"))
} else if let error = error {
completion(.failure(error))
}
}
}
func safelyFetchData(completion: @escaping (Result<String, Error>) -> Void) {
// `[weak self]` ilə açıq ələ keçirilmə - `self?` seçimlidir və `self.` tələb etmir
someAsyncOperation { [weak self] data, error in
guard let self = self else { return } // `self` seçimlidir və açılır
if let data = data {
self.processData(data) // `self.` tələb edilmir
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) {
// Asinxron əməliyyatın simulasyonu
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("Some data", nil)
}
}