Sobes.tech
Middle

Qapanışlarda həmişə `self` parametrini göstərmək lazımdırmı?

sobes.tech Süni İntellekt

AI-dan cavab

Xeyr, həmişə deyil.

self-in açıq şəkildə göstərilməsi yalnız aşağıdakı hallarda tələb olunur:

  1. 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.
  2. 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 üçün self-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)
    }
}