---
title: 'Güçlü, Zayıf ve Sahipsiz Referanslar'
source: 'https://academia.sh/tr/kurslar/swift/guclu-zayif-ve-sahipsiz-referanslar'
course: 'Swift Dili'
language: tr
updated: '2026-10-21T05:03:12+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'İki sınıfın birbirini güçlü tutmasıyla oluşan tutma döngüsünü deinit çıktısından tanır'
    - 'Bir referansı weak yaparak döngüyü kırar ve weak referansın nesne gidince nil olduğunu gözler'
    - 'Ömrü daha uzun olan tarafa unowned referans bağlar'
    - 'Weak ile unowned arasındaki farkı nesne gittikten sonraki okumada ayırt eder'
---

# Güçlü, Zayıf ve Sahipsiz Referanslar

İki sınıfın birbirini güçlü tutunca deinit'in hiç çalışmadığını, weak ve unowned ile döngünün kırıldığını ve unowned referansın nesne gittikten sonra okunamayacağını ölçer.

Önceki derste referans sayısı sıfıra düştü ve `deinit` koştu. Sayının sıfıra düşmesi bir koşuldu, garanti değil. İki sınıf örneği birbirini **güçlü referans** ile tutarsa her biri ötekinin sayacını bir üstte tutar ve dışarıdaki tüm adlar bırakılsa bile ikisi de yaşar. Bu duruma **tutma döngüsü** denir. Bu ders döngüyü kurar, iki yoldan kırar ve her yolda `deinit` gövdesinin ne zaman koştuğunu ölçer.

İki kırma aracı vardır. **Zayıf referans (`weak`)** örneği tutmaz: sayacı artırmaz ve gösterdiği örnek yok edilince kendiliğinden `nil` olur, bu yüzden her zaman isteğe bağlı bir `var` olur. **Sahipsiz referans (`unowned`)** da sayacı artırmaz, ama `nil` olmaz ve isteğe bağlı olmak zorunda değildir; bunun karşılığında gösterdiği örneğin kendisinden uzun yaşayacağı sözünü ister. `Probe` önceki dersteki gibi verilir.

```swift
// Probe.swift — bir ifadenin ne zaman degerlendirildigini kaydeder
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "hic" }
        if evaluations > 1 { return "her-kullanimda" }
        return evaluatedBeforeUse ? "hemen" : "ilk-kullanimda"
    }

    func report() {
        print("\(label): \(evaluations) degerlendirme, \(uses) kullanim -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["hemen", "ilk-kullanimda", "her-kullanimda", "hic"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```


## Tutma Döngüsü

Ölçülen iki sınıf `Account` ve `Profile`'dır. Her ikisinin de `deinit` gövdesi bir satır basar ve ortak `Probe`'a `eval` ile haber verir. `Account` bir `Profile` tutar, `Profile` da bir `Account` tutar; ikisi de varsayılan, yani güçlü referanstır. Her turda iki örnek kurulur, birbirine bağlanır ve ardından ikisine de `nil` atanır. Dışarıdaki adlar böylece bırakılmış olur.

```swift
// main.swift — iki sinif birbirini guclu tutar
final class Account {
    let name: String
    let owner: Probe
    var profile: Profile?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit hesap \(name)")
        _ = owner.eval(name)
    }
}

final class Profile {
    let title: String
    let owner: Probe
    var account: Account?

    init(_ title: String, owner: Probe) {
        self.title = title
        self.owner = owner
    }

    deinit {
        print("deinit profil \(title)")
        _ = owner.eval(title)
    }
}

let cyclic = Probe("tutma-dongusu")

for round in 1...2 {
    var account: Account? = Account("hesap-\(round)", owner: cyclic)
    var profile: Profile? = Profile("profil-\(round)", owner: cyclic)
    account?.profile = profile
    profile?.account = account
    _ = cyclic.use {
        account = nil
        profile = nil
    }
    print("birakildi \(round): \(cyclic.evaluations) deinit")
}

cyclic.report()
```

```
birakildi 1: 0 deinit
birakildi 2: 0 deinit
tutma-dongusu: 0 degerlendirme, 2 kullanim -> hic
```

İki turun ikisinde de bırakmadan sonra `deinit` sayısı sıfırdır ve `deinit` satırı hiç görünmez. Her örnek ötekinin özelliği tarafından tutulduğu için iki sayaç da en az bire eşit kalır. `tutma-dongusu` iki kullanım ve sıfır değerlendirme kaydeder; kural `hic` der. Bu dersin anı bu yüzden **hiç**tir: `deinit` gövdesi hiçbir anda değerlendirilmez. Üstelik hiçbir şey hata vermez. Döngüdeki iki örnek program sonuna kadar bellekte kalır.

## Zayıf Referansla Kırmak

Döngüyü kırmak için iki taraftan yalnız birinin referansı zayıf yapılır. İkinci ölçüm `Profile.account` özelliğini `weak var` olarak tanımlar, başka hiçbir şeyi değiştirmez. Bu kez örnekler iki adımda bırakılır: önce `account`, sonra `profile`. Her adımdan sonra `profile?.account` okunur ve `deinit` sayısı basılır.

```swift
// main.swift — bir taraf zayif tutar
final class Account {
    let name: String
    let owner: Probe
    var profile: Profile?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit hesap \(name)")
        _ = owner.eval(name)
    }
}

final class Profile {
    let title: String
    let owner: Probe
    weak var account: Account?

    init(_ title: String, owner: Probe) {
        self.title = title
        self.owner = owner
    }

    deinit {
        print("deinit profil \(title)")
        _ = owner.eval(title)
    }
}

let broken = Probe("zayif-referans")

for round in 1...2 {
    var account: Account? = Account("hesap-\(round)", owner: broken)
    var profile: Profile? = Profile("profil-\(round)", owner: broken)
    account?.profile = profile
    profile?.account = account
    print("baglandi: \(profile?.account == nil ? "nil" : "dolu")")
    _ = broken.use { account = nil }
    print("hesap birakildi: \(profile?.account == nil ? "nil" : "dolu"), \(broken.evaluations) deinit")
    _ = broken.use { profile = nil }
    print("profil birakildi: \(broken.evaluations) deinit")
}

broken.report()
```

```
baglandi: dolu
deinit hesap hesap-1
hesap birakildi: nil, 1 deinit
deinit profil profil-1
profil birakildi: 2 deinit
baglandi: dolu
deinit hesap hesap-2
hesap birakildi: nil, 3 deinit
deinit profil profil-2
profil birakildi: 4 deinit
zayif-referans: 4 degerlendirme, 4 kullanim -> her-kullanimda
```

Bağlandıktan sonra `profile?.account` doludur. `account` adı bırakıldığında `Account` örneğinin güçlü referansı kalmaz: `profile.account` zayıf olduğu için sayacı artırmamıştı. `deinit hesap hesap-1` satırı hemen çıkar ve ardından gelen okuma `nil` verir; zayıf referans, gösterdiği örnek yok edildiği anda kendiliğinden `nil` olur. `Profile` örneği ise `profile` adıyla hâlâ tutulduğundan yaşar, `deinit profil` satırı ancak o ad bırakılınca görünür. İki turda dört `deinit` koştu ve `zayif-referans` `her-kullanimda` der.

## Sahipsiz Referansla Kırmak

Zayıf referans örneğin yok olabileceğini söyler. Bir ilişki bu yönde değilse, yani `Card` bir `Customer` olmadan hiçbir zaman var olmayacaksa, referans `unowned let` olarak yazılır. Üçüncü ölçüm bu ilişkiyi kurar: `Customer` isteğe bağlı bir `card` tutar, `Card` ise `unowned let customer` taşır. Müşteri kartı tutar, kart müşteriyi tutmaz. Ölçüm yalnız müşteri adını bırakır.

```swift
// main.swift — sahipsiz referans daha uzun yasayana baglanir
final class Customer {
    let name: String
    let owner: Probe
    var card: Card?

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit musteri \(name)")
        _ = owner.eval(name)
    }
}

final class Card {
    let number: String
    let owner: Probe
    unowned let customer: Customer

    init(_ number: String, customer: Customer, owner: Probe) {
        self.number = number
        self.customer = customer
        self.owner = owner
    }

    deinit {
        print("deinit kart \(number)")
        _ = owner.eval(number)
    }
}

let bound = Probe("sahipsiz-referans")

for round in 1...2 {
    var customer: Customer? = Customer("musteri-\(round)", owner: bound)
    if let current = customer {
        current.card = Card("kart-\(round)", customer: current, owner: bound)
        print("kart sahibi: \(current.card?.customer.name ?? "yok")")
    }
    _ = bound.use { customer = nil }
    print("birakildi \(round): \(bound.evaluations) deinit")
}

bound.report()
```

```
kart sahibi: musteri-1
deinit musteri musteri-1
deinit kart kart-1
birakildi 1: 2 deinit
kart sahibi: musteri-2
deinit musteri musteri-2
deinit kart kart-2
birakildi 2: 4 deinit
sahipsiz-referans: 4 degerlendirme, 2 kullanim -> her-kullanimda
```

Her turda `deinit musteri` satırı `deinit kart` satırından önce gelir. Müşteri bırakılınca sayacı sıfıra düşer, `deinit` gövdesi koşar, ardından özellikleri bırakılır ve kartın tek güçlü referansı da gider. Bu zincirde döngüyü kıran, kartın müşteriyi güçlü tutmamasıdır; `unowned` bunu isteğe bağlı olmadan ifade eder. `sahipsiz-referans` iki kullanım ve dört değerlendirme kaydeder, iki `deinit` her turda koşar ve kural `her-kullanimda` der.

## Temsilci Deseni

Zayıf referansın en yaygın yeri temsilci desenidir: bir nesne işini bitirince haber vereceği ikinci bir nesneyi saklar, haber alan ise işi yapan nesneyi zaten tutar. İki yönün de güçlü olması tutma döngüsü kurardı. Bu ölçüm `Worker` sınıfının `weak var delegate` özelliğini kullanır; `Reporter` ise `Worker`'ı güçlü tutar. Tur sonunda yalnız `reporter` adı bırakılır ve `worker` adı elde kalır.

```swift
// main.swift — temsilci zayif, calisan guclu
final class Reporter {
    let name: String
    let owner: Probe
    let worker: Worker

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
        worker = Worker()
        worker.delegate = self
    }

    deinit {
        print("deinit raporlayici \(name)")
        _ = owner.eval(name)
    }
}

final class Worker {
    weak var delegate: Reporter?
}

let handedOver = Probe("temsilci")
for round in 1...2 {
    var reporter: Reporter? = Reporter("raporlayici-\(round)", owner: handedOver)
    let worker = reporter!.worker
    print("temsilci \(worker.delegate?.name ?? "nil")")
    _ = handedOver.use { reporter = nil }
    print("birakildi: temsilci \(worker.delegate?.name ?? "nil"), \(handedOver.evaluations) deinit")
}

handedOver.report()
```

```
temsilci raporlayici-1
deinit raporlayici raporlayici-1
birakildi: temsilci nil, 1 deinit
temsilci raporlayici-2
deinit raporlayici raporlayici-2
birakildi: temsilci nil, 2 deinit
temsilci: 2 degerlendirme, 2 kullanim -> her-kullanimda
```

Bağlandıktan sonra `worker.delegate` raporlayıcının adını verir. `reporter` adı bırakıldığında `Reporter` örneğinin güçlü referansı kalmaz: `Worker` onu zayıf tuttuğu için sayacı artırmamıştı. `deinit raporlayici raporlayici-1` satırı hemen çıkar ve ardından gelen okuma `nil` verir. `worker` ise `worker` adıyla elde tutulduğundan yaşamaya devam eder; `Reporter` onu özelliğinde tuttuğu halde kendisi gittiği için `Worker`'ın payı yalnız dışarıdaki addır. Desenin işleyişi bu asimetriye dayanır: haber alan, haber verenden uzun yaşamak zorunda değildir ve haber veren, haber alanın gittiğini `nil` okuyarak öğrenir. Bu yüzden temsilci özelliği her zaman isteğe bağlı bir değer olarak yazılır ve her kullanımdan önce kontrol edilir. İki turda iki `deinit` koşar ve `temsilci` `her-kullanimda` der.

## Zayıf ve Sahipsiz Okuma

İki referans biçimi, gösterdikleri örnek yaşadığı sürece aynı değeri verir. Ayrım örnek gittikten sonra başlar. Bu ölçüm bir `Watcher` kurar: biri `weak var`, öteki `unowned let` iki özellik aynı `Target` örneğini gösterir. Örnek yaşarken ikisi de okunur, sonra örnek bırakılır ve yalnız zayıf özellik okunur. Sahipsiz özellik bu noktadan sonra okunmaz; okuma programı durdururdu.

```swift
// main.swift — ayni hedefe zayif ve sahipsiz bakis
final class Target {
    let name: String
    let owner: Probe

    init(_ name: String, owner: Probe) {
        self.name = name
        self.owner = owner
    }

    deinit {
        print("deinit hedef \(name)")
        _ = owner.eval(name)
    }
}

final class Watcher {
    weak var soft: Target?
    unowned let strict: Target

    init(_ target: Target) {
        soft = target
        strict = target
    }
}

let looked = Probe("zayif-ve-sahipsiz")
for round in 1...2 {
    var target: Target? = Target("hedef-\(round)", owner: looked)
    let watcher = Watcher(target!)
    print("yasarken: zayif \(watcher.soft?.name ?? "nil"), sahipsiz \(watcher.strict.name)")
    _ = looked.use { target = nil }
    print("gittikten sonra: zayif \(watcher.soft?.name ?? "nil")")
}

looked.report()
```

```
yasarken: zayif hedef-1, sahipsiz hedef-1
deinit hedef hedef-1
gittikten sonra: zayif nil
yasarken: zayif hedef-2, sahipsiz hedef-2
deinit hedef hedef-2
gittikten sonra: zayif nil
zayif-ve-sahipsiz: 2 degerlendirme, 2 kullanim -> her-kullanimda
```

Örnek yaşarken iki okuma da `hedef-1` verir; iki biçim bu anda birbirinden ayırt edilemez. `deinit hedef hedef-1` satırından sonra zayıf okuma `nil` verir: örnek yok edildikten sonra zayıf referans `nil` okunur. Sahipsiz okuma ise aynı noktada ölçülmez: `strict.name` satırı gitmiş bir örneği okuyacaktı ve çalışma zamanı programı durdururdu. Bu nedenle iki biçim arasındaki seçim bir okuma biçimi seçimi değil, ne olması gerektiği sözüdür. Hedefin `watcher`'dan önce gitmesi mümkünse zayıf, imkânsızsa sahipsiz yazılır. `zayif-ve-sahipsiz` iki turda iki değerlendirme sayar ve `her-kullanimda` der; zayıf okumanın sonucu ise her okuma anında yeniden belirlenir. Önceki okumanın sonucu sonraki okumaya taşınmaz.

## Sınırlayıcı Ölçüm

Zayıf ve sahipsiz referans yalnız gösterdiklerini tutmamakta ortaktır; gösterdikleri örnek gittikten sonra okunduklarında ayrılırlar. Zayıf referans `nil` verir ve bunu ikinci ölçüm yukarıda gösterdi. Sahipsiz referansın böyle bir güvencesi yoktur: gitmiş bir örneğe `unowned` ile erişmek çalışma zamanında programı durdurur. Bu yüzden bu okuma ölçülmez. Aşağıdaki parça yalnız kaynaktır ve çalıştırılmaz. Çıktı iddiası da yoktur.

```swift
// Kaynak parca: calistirilmaz
var customer = Customer("musteri-3", owner: bound)
let card = Card("kart-3", customer: customer, owner: bound)
customer = Customer("musteri-4", owner: bound)
print(card.customer.name)
```

Üçüncü satır `musteri-3`'ün son güçlü referansını bırakır; `Card` onu tutmadığı için örnek yok edilir. Dördüncü satır yok edilmiş bir örneği okur. Aynı yapı `weak` ile yazılsaydı okuma `nil` verirdi ve program devam ederdi. Seçim bu yüzden bir ömür sözüdür: `unowned` yalnız referansı taşıyan örnekten daha uzun yaşadığı kesin olan bir örneğe bağlanır; emin olunmayan her yerde `weak` kullanılır. Derleyici bu sözü denetlemez, bu yüzden bu bir sınırdır, bir an değil.

**BL2.** Her bağlantı biçimi için tek bir sınıf çifti ölçüldü; üç çiftin hepsi iki sınıflı küçük zincirlerdir. Daha uzun döngülerde (üç ve daha çok sınıf) aynı kuralın geçtiği bu derste gösterilmedi. Çiftlerin seçimi tasarım tercihidir.

## Özet

- İki sınıf birbirini güçlü tutarsa referans sayıları sıfıra düşmez ve iki `deinit` de koşmaz; bu bir tutma döngüsüdür.
- Bir tarafı `weak var` yapmak döngüyü kırar; zayıf referans gösterdiği örnek yok edilince `nil` olur.
- `unowned let` ömrü daha uzun olan tarafa bağlanır ve `nil` olmaz; yok edilmiş örneği okumak programı durdurur, bu yüzden ölçülmez.
- Bu dersin anı: **hiç**. Tutma döngüsündeki `deinit` gövdesi hiçbir anda değerlendirilmez; döngü kırıldığında her turda koşar.

## Sonraki Adım

Bu derste döngü iki sınıf özelliği arasında kuruldu. Bir sınıfın kendi özelliğinde sakladığı kapanış da `self`'i güçlü yakalayarak aynı döngüyü kurabilir ve bu, tutma döngülerinin en sık rastlanan biçimidir. Sonraki ders kapanışlarda yakalamayı ve `[weak self]` yakalama listesinin ne zaman değerlendirildiğini ölçer.
