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:
- 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. - 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.) veself'i örtük olarak yakalarsanız, derleyici açıkçaself'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)
}
}