← Back to list

Swift’te ARC (Automatic Reference Counting) ile Bellek Yönetimi

Swift, C veya C++ gibi dillerin aksine, geliştiriciden doğrudan hafıza yönetimi yapmasını beklemez. Ancak bu rahatlık, bazen büyük…

Umutkonmus · 2025-07-21 15:08 · 0 claps · 2.7 min read
#swift #ios-development #memory-management #retain-cycle #software-engineering
Open on Medium ↗
Wiki topics: BIZ · Business Strategy 📱 · Mobile Development 🧘 · Spirituality

Swift’te ARC (Automatic Reference Counting) ile Bellek Yönetimi

Bunun ARC olduğunu düşünebilirsiniz :)

Bunun ARC olduğunu düşünebilirsiniz :)

Swift, C veya C++ gibi dillerin aksine, geliştiriciden doğrudan hafıza yönetimi yapmasını beklemez. Ancak bu rahatlık, bazen büyük sorunlara da yol açabiliyor. Ben de ilk “retain cycle” hatamı aldığımda ARC’nin aslında ne kadar önemli olduğunu fark ettim.

ARC Nedir ?

Automatic Reference Counting (ARC), Swift’te referans tiplerinin (class) bellekte ne zaman oluşturulacağı ve yok edileceğini kontrol eden bir sistemdir.

  • Her class türü nesne oluşturulduğunda, ARC ona bir referans sayacı atar.
  • Başka bir referans, bu nesneyi tuttuğunda sayaç 1 artar.
  • Referans kaldırıldığında sayaç azalır.
  • Sayaç 0 olduğunda, ARC nesneyi bellekten siler (deinit çağrılır).
class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) init")
    }
    deinit {
        print("\(name) deinit")
    }
}

var person1: Person? = Person(name: "UK") // referans sayısı 1 artar => 1
var person2 = person1 // referans sayısı 2

person1 = nil // referans sayısı 1
person2 = nil // referans sayısı 0 → deinit çağrılır

Bu örnekte her şey kontrol altında. Ancak işin içine closure, delegate gibi yapılar girdiğinde işler karmaşıklaşıyor.

Strong ve Weak Referans Nedir?

Swift’te ARC sistemi her referansı aynı şekilde değerlendirmez. Referans tiplerinin bellekte nasıl tutulacağını belirlemek için strong, weak, ve unowned gibi referans türleri kullanırız. ARC’nin nasıl çalıştığını anlamak için özellikle strong ve weak farkını bilmek kritiktir.

Strong Referans (varsayılan)

  • Her değişken varsayılan olarak bir nesneyi strong referansla tutar.
  • Bu, ARC sayacını 1 artırır.
var a = MyClass()
var b = a // b de strong referans

Bu yüzden a ve b nil olmadan nesne bellekten atılamaz.

a = nil // referans sayısı 1
b = nil // referans sayısı 0 → deinit çağrılır

Weak Referans

  • ARC sayacını artırmaz.
  • Nesne silindiğinde otomatik olarak nil olur.
  • Bu yüzden sadece opsiyonel (?) olarak tanımlanabilir.
class Owner {
    var pet: Pet?
}

class Pet {
    weak var owner: Owner? // ← strong yerine weak referans
}

Burada:

  • OwnerPet strong tutar.
  • PetOwner weak tuttuğu için ARC sayacını artırmaz.
  • İki sınıf birbirine işaret etse bile retain cycle oluşmaz.

⚠️ weak referanslar opsiyonel (?) olmalıdır. Çünkü ARC nesneyi yok ettiğinde referans otomatik olarak nil olur.

Retain Cycle Nedir?

Retain cycle, iki (veya daha fazla) nesnenin birbirini strong referansla tutarak, ARC’nin referans sayısını sıfıra düşürememesi durumudur. Bu durumda nesneler hafızada kalır ve deinit tetiklenmez; bu da bir memory leak’tir.

Basit bir örnek :

class A {
    var b: B?
}

class B {
    var a: A?
}

var objA: A? = A()
var objB: B? = B()

objA?.b = objB
objB?.a = objA

objA = nil
objB = nil

Bu kodda A ve B sınıfları karşılıklı olarak birbirine strong referans verdiği için:

  • objA silinmez çünkü objB.a hâlâ onu tutar.
  • objB silinmez çünkü objA.b hâlâ onu tutar.

Sonuç: İki nesne de bellekten atılamaz → Memory leak.

Çözüm: Weak Referans Kullanmak

class B {
    weak var a: A?
}

Bu sayede B sınıfı içindeki a değişkeni ARC tarafından referans sayacına dahil edilmez. Biri silindiğinde diğerinin yaşam döngüsü tamamlanır → Retain cycle kırılır.

Closure Yoluyla Retain Cycle’a Sebep Olma

❌ Problemli Kod:

class MyViewModel {
    var onDataFetched: (() -> Void)?

    func fetchData() {
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
            self.onDataFetched?()
        }
    }
}

Bu kodda self closure içinde strong olarak tutuluyor. Bu closure da self içinde bir property olduğundan retain cycle oluşuyor:

  • MyViewModel → closure (strong)
  • closure → MyViewModel (strong)

Bu döngü asla kırılmadığı için ARC nesneyi temizlemiyor.

✅ Çözüm: Weak Capture List

func fetchData() {
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) { [weak self] in
        self?.onDataFetched?()
    }
}
  • [weak self] ile self artık ARC sayacını artırmaz.
  • self nil olmuşsa bile uygulama çökmez.

Bu refleksi kazanmak zaman alıyor ama kritik. Bir ViewModel’de *[weak self]* koymayı unuttuğumda ekranda “ghost ViewController” kalıntılarıyla çok uğraştım.

Sonradan Edindiğim Alışkanlıklar

  • [weak self]’i closure’larda refleks olarak kullanıyorum.
  • Delegate’leri her zaman weak tanımlıyorum.
  • Xcode Memory Graph’ı düzenli kullanıyorum.

Swift’te ARC, düşük seviyeli belleği bizden saklar. Ama bu onun sorunsuz olduğu anlamına gelmez.

ARC’yi anlamak, Swift’te başarılı olmanın yegane yoludur. Ben kendi retain cycle’larımla mücadele ederken, hem kod kalitemi hem de düşünme şeklimi değiştirdim. Umarım siz mücadele etmeden anlayabilirsiniz.


메타데이터
post_id
0d45ecc010f4
slug
swiftte-arc-automatic-reference-counting-ile-bellek-yönetimi-0d45ecc010f4
url
https://medium.com/@umutkonmus/swiftte-arc-automatic-reference-counting-ile-bellek-y%C3%B6netimi-0d45ecc010f4
canonical_url
https://medium.com/@umutkonmus/swiftte-arc-automatic-reference-counting-ile-bellek-y%C3%B6netimi-0d45ecc010f4
author_url
https://medium.com/@umutkonmus
status
ok
fetched_at
2026-07-16 05:33:41