ProgramlamaiOS geliştirici

Swift'te otomatik sahiplik aktarımı (Automatic Reference Counting, ARC) mekanizmasını ve bunun bellek yönetimi ile olan ilişkisini açıklayın.

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Soru tarihi:

Objective-C'nin gelişimi ve Swift'in ortaya çıkmasıyla birlikte Apple, geliştiricilerin retain/release komutlarıyla manuel hafıza yönetimi yapmadan uygulama belleğini otomatik ve güvenli bir şekilde yönetme sorunu ile karşı karşıya kaldı. Swift, sınıf nesnelerine olan referans sayısını takip eden ve son sahibi kaybolduğunda belleği otomatik olarak serbest bırakan Automatic Reference Counting (ARC) kullanır.

Sorun:

Swift, çoklu paradigma dilidir, hem değer tipleri (struct, enum) hem de referans tipleri (class) ile çalışır. Referans tipleri için belleğin zamanında temizlenmesi önemlidir, aksi takdirde bellek sızıntısı oluşabilir. Komplike bir durum, iki nesnenin birbirine referans vermesiyle oluşan retain cycle (döngüsel referanslar) olduğunda, bu durumda ARC belleği serbest bırakamaz.

Çözüm:

Swift, yalnızca sınıf nesnelerine ARC uygular. Referans sayısı 0 olduğunda belleği serbest bırakır. Retain cycle problemini çözmek için weak/unowned anahtar kelimeleri kullanılır.

Kod örneği:

class Person { var name: String var pet: Pet? init(name: String) { self.name = name } deinit { print("\(name) deinitializasyon aşamasında") } } class Pet { var owner: Person? init() {} deinit { print("Pet deinitializasyon aşamasında") } } var tom: Person? = Person(name: "Tom") var cat: Pet? = Pet() tom!.pet = cat cat!.owner = tom tom = nil cat = nil // Her iki nesne SERBEST BIRAKILMAZ, retain cycle oluşur

Anahtar özellikler:

  • Bellek yönetimi geliştirici için şeffaftır.
  • Sadece sınıflar desteklenmektedir; struct ve enum'lar referans takibi yapılmaz.
  • Retain cycle'ı çözmek için weak ve unowned kullanılır.

Kandırmaca sorular.

Değer tipleri için ARC uygulanabilir mi?

Hayır, ARC yalnızca sınıf nesnelerine olan referansları takip eder. Yapılar ve enum'lar değer üzerinden geçirilir ve Swift bunların belleğini otomatik olarak serbest bırakır (genellikle kapsamdan çıktıklarında).

İki karşılıklı referans veren nesnenin özelliklerinde weak/unowned kullanılmazsa ne olur?

Döngüsel referans (retain cycle) oluşur ve bu nedenle ARC bu nesneler için bellek serbest bırakamaz. Bu tür bir kod, bellek sızıntısına yol açar — bu nedenle benzer bir ilişkide en az bir taraf için her zaman weak (veya unowned) kullanın.

Weak varken unowned'a neden ihtiyaç vardır?

Unowned, bir nesnenin yaşam süresi boyunca başka bir nesne tarafından her zaman sahip olunması gerektiğinde ve asla nil olmaması gerektiğinde gereklidir. Weak — null referans, unowned — null değil ama retain sayacı artışı yoktur.

Kod örneği:

class A { var b: B? } class B { unowned var a: A // B'nin yaşamı boyunca asla nil olmaz }

Tipik hatalar ve anti-paternerler

  • Weak/alınan unowned gerektiği durumlarda güçlü referansların kullanılması.
  • Sınıflar ve nesne içeren diziler/kelimelikler üzerinde çalışırken ARC'nin unutulması.
  • Değer tiplerinin belleğini manuel olarak serbest bırakmaya veya struct/enum için weak kullanmaya çalışmak.

Hayattan bir örnek

Olumsuz vaka

İki kontrolör birbirlerine güçlü referanslar taşır: biri — delegasyon özelliğiyle, diğeri — alt kontrolörler dizisiyle. Oluşturucu, delegasyonda weak kullanmamaktadır.

Artılar: Hatalar hemen görülmez, her şey "ilk bakışta çalışıyormuş gibi" gözükür.

Eksiler: Uygulama büyüdükçe bellek serbest bırakılmaz, sızıntılar oluşur; sınırlı bellek ile çalışırken çökme riski vardır.

Olumlu vaka

Delegasyon ve olay gözlemcisi weak olarak ayarlanır, kontrolör dizisi kontrolörlerin kaybolduğu ölçüde temizlenir. Her şey düzgün bir şekilde belgelenmiştir.

Artılar: Bellek sızıntısı yok, tüm nesneler zamanında serbest bırakılır, performans kaybı yoktur.

Eksiler: Delegenin beklenmedik bir şekilde kaybolması mümkündür (eğer yukarıda güçlü bir referans unutulmuşsa); uygulama mimarisinde dikkat gerektirir.