Sobes.tech
Middle

Kapanışlarda her zaman `self` parametresini belirtmek gerekir mi?

sobes.tech yapay zeka

AI'dan gelen yanıt

Hayır, her zaman değil.

self'in açıkça belirtilmesi gereken durumlar yalnızca aşağıdaki durumları kapsar:

  1. Erişilmeyen (non-escaping) kapanışlarda: Bu, derleyicinin self'in yakalanmasını açıkça belirtmesi için gereklidir. Teknik olarak yakalama gerçekleşir, ancak bu fonksiyon içinde olur ve güçlü referans döngülerine yol açmaz.
  2. Erişen (escaping) kapanışlarda, varsayılan olarak self'in yakalanması (örtük yakalama): Eğer kapanış, tanımlandığı fonksiyonun kapsamını dışarı çıkarsa (örneğin, bir asenkron işlemi geçerken, bir özelliğe kaydedilir vb.) ve self'i örtük olarak yakalarsanız, derleyici açıkça self'i belirtmenizi isteyecektir, böylece olası güçlü referans döngüleri netleşir.

Diğer durumlarda (örneğin, [weak self] veya [unowned self] kullanılarak yapılan kapanışlar), self'i belirtmek gerekmez, çünkü sahiplik ilişkisi açıkça kontrol edilir.

Örnek:

class MyClass {
    var value = 10

    func doSomething() {
        // Erişilmeyen kapanış - `self` gerekir
        UIView.animate(withDuration: 0.3) {
            self.value = 20
        }
    }

    func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
        // Erişen kapanış, örtük `self` yakalama - `self` gerekir
        // `[weak self]` kullanılmazsa güçlü referans döngüsü oluşabilir
        someAsyncOperation { data, error in
            if let data = data {
                // Örtük yakalama kullanıldığında `self` gerekmez
                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]` ile açık yakalama kullanımı - `self?` opsiyoneldir ve `self.` gerekmez
        someAsyncOperation { [weak self] data, error in
            guard let self = self else { return } // `self` opsiyonel olarak açılır

            if let data = data {
                self.processData(data) // `self.` gerekmez
                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) {
    // Asenkron işlem simülasyonu
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        completion("Some data", nil)
    }
}