Weak Reference (zayıf referans), ARC'de bir nesnenin tutma sayacını artırmayan bir referanstır. Apple Swift Language Guide, 2026'ya göre, zayıf referanslar weak anahtar kelimesiyle bildirilir ve her zaman isteğe bağlıdır. Nesne serbest bırakıldığında, ona yapılan tüm zayıf referanslar otomatik olarak nil olarak ayarlanır, bu da sarkan işaretçileri önler ve zayıf referansları tutma döngülerini kırmak için güvenli bir mekanizma haline getirir.
Anahtar Noktalar
weak anahtar kelimesi; tür her zaman isteğe bağlı (?)Weak Reference, ARC'de (Automatic Reference Counting) bir nesneye yapılan sahip olmayan referanstır. Nesnenin retain count'ını artıran ve yaşam süresini garanti eden güçlü referansın aksine, zayıf referans, nesnenin hala referans veriliyor olsa bile serbest bırakılmasına izin verir. Serbest bırakıldıktan sonra, zayıf referans otomatik olarak nil olarak ayarlanır — buna zeroing weak denir.
Zeroing weak, Swift ve Objective-C çalışma zamanının önemli bir özelliğidir. Bir nesnenin referans sayacı sıfıra ulaştığında ve nesne serbest bırakıldığında, çalışma zamanı bu nesneye yapılan tüm zayıf referansları (özel bir zayıf tabloda saklanan) dolaşır ve bunları nil olarak ayarlar. Bu, zayıf referanslar aracılığıyla serbest bırakılmış belleğe erişimin (use-after-free) imkansız olmasını sağlar — herhangi bir okuma nil döndürür.
Apple WWDC 2012 Session 406'ya göre, zeroing weak referanslar, manuel bellek yönetiminde (MRR) yaygın olan sarkan işaretçilerle (dangling pointers) ilgili bir dizi çökme hatasını ortadan kaldırdı. MRR'de, zayıf referanslar yalnızca __unsafe_unretained olarak mevcuttu — sıfırlanmazlardı ve serbest bırakılmış bir nesneye erişim EXC_BAD_ACCESS'e neden olurdu.
Apple ekosisteminin her iki dilinde de zayıf referans bildirme sözdizimine bakalım. Paylaşılan çalışma zamanına rağmen, sözdizimi farklıdır, ancak anlambilim aynıdır.
Swift'te, zayıf referanslar var'dan önce weak anahtar kelimesiyle bildirilir. Tür her zaman isteğe bağlı (Tür?) olmalıdır, çünkü referans herhangi bir zamanda nil olabilir. Sabitler (let) weak olamaz — yalnızca değişkenler.
class ViewController: UIViewController {
// weak properties: only var, only optional
weak var delegate: ViewControllerDelegate?
weak var parentView: UIView?
weak var completionHandler: ((Bool) -> Void)? // ⚠️ closure'lar weak depolamaz
// ⬆️ Hata: weak yalnızca class türlerine uygulanabilir, closure'lara değil
}
Önemli: weak yalnızca sınıf örneklerine (class türleri), AnyObject'e ve AnyObject'ten türetilmiş protokollere uygulanabilir. Struct, enum ve closure'lar weak olamaz — bunlar değer türleridir ve ARC'ye katılmazlar.
Objective-C'de, zayıf özellikler __weak niteliği veya özellik bildirimlerinde weak değiştiricisi kullanılarak bildirilir:
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end
// Yerel weak değişkeni
__weak MyObject *weakRef = someStrongObject;
Objective-C çalışma zamanı da zeroing weak sağlar, ancak ek olarak C yapıları ve bazı Core Foundation nesneleriyle weak kullanımını engeller. Bunlar için __unsafe_unretained kullanılır — zeroing olmadan.
Zayıf referanslar evrensel bir çözüm değil, belirli senaryolar için bir araçtır. Her yerde weak kullanmak gereksiz karmaşıklığa yol açar ve okunabilirliği bozar. Doğru kullanım senaryolarına bakalım.
Temsilciler — weak için birincil senaryo. Sahip olan nesne (örneğin UITableView) kendisine güçlü bir referans tutarken, temsilci (UIViewController) tabloya sahip olmamalıdır. Apple SDK, tüm temsilcilerin ve dataSource'ların weak olduğunu garanti eder. Kendi protokolleriniz için her zaman weak var delegate kullanın.
Bir çocuk nesnenin ebeveynine referans vermesi gerektiğinde (örneğin, ChildViewController'ın bir koordinatöre erişmesi), zayıf bir referans kullanın. Ebeveyn çocuğa sahiptir (strong), çocuk ebeveyni gözlemler (weak) — tutma döngüsü ortadan kalkar.
Capture list [weak self] — sınıf özellikleri olarak saklanan closure'larda tutma döngülerini önlemenin standart yoludur. Self, closure tamamlanmadan önce serbest bırakılabiliyorsa, weak self zorunludur.
| Senaryo | Weak | Strong |
|---|---|---|
| Temsilci | ✅ Her zaman weak | ❌ Tutma döngüsü |
| Ebeveyn → Çocuk | ❌ Gerekli değil (ebeveyn sahip olmalı) | ✅ Strong |
| Çocuk → Ebeveyn | ✅ Weak | ❌ Tutma döngüsü |
| Asenkron geri çağrı | ✅ [weak self] | ❌ Tutma döngüsü riski |
| Güçlü bağlantı (owned) | ❌ unowned | ✅ Strong |
Genel kural: A nesnesi B'ye sahipse (A → B strong), o zaman B → A weak veya unowned olmalıdır. Güçlü referansların yönü her zaman sahipten asta doğru olmalıdır.
Hem weak hem de unowned retain count'ı artırmaz, ancak nesne serbest bırakıldıktan sonraki davranışta farklılık gösterir. Aralarındaki seçim, yaşam süresi garantileri meselesidir.
Weak: otomatik olarak nil olur, tür her zaman isteğe bağlıdır, kullanımdan önce açma gerektirir. Güvenli — nil'e erişim çökmeye neden olmaz.
Unowned: nil olmaz, tür isteğe bağlı değildir. Nesne serbest bırakılırsa, unowned referans sarkan bir işaretçi haline gelir — ona erişmek çalışma zamanı çökmesine neden olur. Unowned, nesnenin referans veren taraf kadar en azından yaşadığını varsayar.
Weak'i seçin: nesne herhangi bir zamanda serbest bırakılabiliyorsa (ekran kapatıldıktan sonra temsilci), nesnenin yaşam süresini kontrol etmiyorsanız veya garantilerden emin değilseniz. Weak evrensel güvenli seçimdir.
Unowned'ı seçin: nesnenin referans veren nesneden önce serbest bırakılmayacağı garanti ediliyorsa (örneğin, Müşteri → KrediKartı, kartın müşteri olmadan var olamayacağı gibi). Unowned, açma gerektirmeyen isteğe bağlı olmayan bir API sağlar, bu da kodda daha kullanışlıdır.
class Order {
let id: Int
var items: [Item] = []
init(id: Int) { self.id = id }
// Güçlü ilişki: Order, Item'a sahip
func addItem(name: String) {
let item = Item(name: name, order: self)
items.append(item)
}
}
class Item {
let name: String
unowned let order: Order // ✅ unowned — Item, Order olmadan yaşamaz
init(name: String, order: Order) {
self.name = name
self.order = order
}
}
// Weak ile örnek: yaşam süresi garantisi olmayan temsilci
protocol NetworkServiceDelegate: AnyObject {
func didReceiveResponse(data: Data)
}
class NetworkService {
weak var delegate: NetworkServiceDelegate? // ✅ weak — temsilci gidebilir
}
Örnekte, Item unowned kullanır çünkü bir sipariş öğesi siparişin kendisi olmadan var olamaz — yaşam süresi garantisi sağlamdır. NetworkService weak kullanır çünkü temsilci (örneğin, ViewController) herhangi bir zamanda kapatılabilir ve serbest bırakılabilir.
Zayıf referanslar güçlü bir araçtır, ancak iOS geliştirmede doğru kullanım için anlaşılması önemli olan sınırlamaları vardır.
Zayıf referanslar güçlü olanlardan daha yavaştır: her erişimde, çalışma zamanı nesnenin serbest bırakılıp bırakılmadığını kontrol eder (zayıf tabloda arama). Senaryoların büyük çoğunluğunda fark hissedilmez, ancak milyonlarca erişimi olan sıcak döngülerde weak darboğaz haline gelebilir. Yüksek yük senaryoları için strong kullanın ve mimariyi yeniden düzenleyin.
Struct, enum, tuple — ARC'ye katılmayan değer türleri. Weak struct bildirmeye çalışmak derleme hatasına neden olur. Bir değer türüne zayıf referans depolamak için, bir sınıf türünde sarmalayıcı veya closure kullanın.
Zeroing weak iş parçacığı güvenlidir: bir nesne bir iş parçacığında serbest bırakılırsa, zayıf referans tüm iş parçacıklarında atomik olarak sıfırlanır. Ancak, zayıf bir referansı okuma ve referansını kaldırma arasındaki pencere bir yarış durumuna yol açabilir — nesne, zayıf referansın alınması ile kullanılması arasında serbest bırakılır. Çözüm: zayıf referansın yerel bir değişkene güçlü yakalanması.
// Çoklu iş parçacığında weak ile yarış durumu
func performAsync() {
weak var weakSelf = self
queue.async {
// ⚠️ weakSelf, kontrol ve kullanım arasında nil olabilir
if weakSelf != nil {
weakSelf!.doSomething() // nil olursa CRASH
}
}
}
// ✅ Düzeltme: kullanım sırasında güçlü yakalama
func performAsyncSafe() {
queue.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.doSomething() // strongSelf — yerel güçlü referans
}
}
Güvenli sürümde, weak self yakalanır, ardından hemen yerel bir güçlü değişken olan strongSelf'e açılır. Self hala yaşıyorsa, blok süresince yaşamaya devam eder. Değilse, guard tetiklenir ve kod yürütülmez. Bu deyim, Swift'te asenkron closure'lar için standart desendir.
IBOutlet Interface Builder'da weak olmalıdır çünkü görünüm hiyerarşisi zaten alt görünüme güçlü bir referans tutar. Denetleyicide güçlü bir referansı kopyalamak bir tutma döngüsü oluşturmaz ancak gereksizdir. Bir outlet'e zayıf referans Apple'ın tavsiyesidir, ancak birçok geliştirici kod basitliği için strong kullanır.
Sıkça Sorulan Sorular
Hayır, weak yalnızca var olan bir nesneyi veya nil'i gösterebilir. Yeni bir nesne oluştururken, önce güçlü bir referans alırsınız (bir başlatıcı aracılığıyla) ve ancak ondan sonra zayıf bir referans atayabilirsiniz. Başlangıçta weak nil normal bir durumdur.
Weak, yalnızca referans türlerini (sınıflar) yöneten ARC'ye dayanır. Değer türleri (struct, enum) atamada kopyalanır ve retain count'a sahip değildir. Değer türleriyle zayıf ilişkiler için, bir sınıfta weak özelliği olan sarmalayıcılar veya closure'lar kullanın.
Zayıf bir referansa her erişim, çalışma zamanı tablosunda bir arama gerçekleştirir. Milyonlarca yinelemeli bir döngüde, bu güçlü bir referanstan 2–5 kat daha yavaş olabilir. Sıcak yollar için, döngüden önce weak'i yerel bir güçlü değişkene kopyalayın.
Nesneye yapılan tüm güçlü referanslar kaybolduğunda — kapsam sonunda, bir özellik yeniden atandığında veya bir ekran kapatıldığında. Çok iş parçacıklı bir ortamda, bu iki kod satırı arasında gerçekleşebilir. Zayıf referansları her zaman guard let veya if let ile kontrol edin.
Anlambilimsel olarak aynı: her ikisi de zeroing weak sağlar. Farklar: Swift isteğe bağlı tür ve var gerektirir, Objective-C bir özellik değiştiricisi kullanır. Objective-C ayrıca __unsafe_unretained — zeroing olmadan zayıf referans (sarkan işaretçi riski) destekler.
Özet
weak var + isteğe bağlı tür; yalnızca class türleri ve AnyObject protokolleriAnahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun