Bu yazıda, Apple’ın Swift’deki bellek yönetiminin nasıl olduğunu inceleyeceğiz. Çoğunlukla otomatik olarak ele alınsa bile, hala bazı önemli noktalar vardır. Nesneler arasındaki ilişkiyi tanımlamak için doğru referans tipini seçmek, hafıza sızıntılarını önlememize yardımcı olur.
Genellikle bu konu iş mülakatlarında soru olarak gelmektedir.
Otomatik Referans Sayacı
Apple’ın bellek kullanımının otomatik olarak izlenmesine ve yönetilmesine yönelik uygulamasına ARC (Otomatik Referans Sayacı - Automatic Reference Counting) adı verilir. Nesneler artık referans alınmadığında belleği otomatik olarak boşaltır. Hangi nesnelerin hala kullanımda olduğunu bilmek için referans sayısını arttırıp azaltarak nesneler arasındaki ilişkiyi izler. Referans sayısı sıfır olduğunda nesneler serbest bırakılabilir. ARC yalnızca Sınıf(Class) örnekleri için geçerlidir. Yapılar, Enums'ler ve Değer Türleri referans tipte değildir. Sınıflar yerine Yapıları kullanmak bu konuda daha avantajlı bir nedendir diyebiliriz.Strong
Swift'te neredeyse her yerde strong referanslar bulacaksınız çünkü bu bir nesnenin varsayılanıdır. Doğrusal bir referans akışınız olduğunda bu bir soruna yol açmaz. Eğer ebeveyni serbest bıraktığınızda ve referans sayısını azalttığınızda tüm çocuklar da azalır. İşte strong bir referans örneği:import Foundation
class Car {
var brand: String
init(brand: String) {
self.brand = brand
print("Car of the brand \(brand) allocated")
}
deinit {
print("Car of the brand \(brand) is being deallocated")
}
}
do {
let tesla = Car(brand: "tesla")
}
Araba nesnesinin başlangıcı do bloğundadır. Bu onun etrafında bir alan yaratır. Nesne do bloğundan dolayı serbest bırakılır ve her şey yolunda girer:
//Car of the brand tesla allocated
//Car of the brand tesla is being deallocated
Ancak, sınıf örnekleri arasında strong bir referans döngüsü olan bir kod yazmak mümkündür. Önceki örneğin bu değiştirilmiş versiyonu bir referans döngüsü gösterir:
import Foundation
class Car {
var brand: String
var owner: Owner?
init(brand: String) {
self.brand = brand
print("Car of the brand \(brand) allocated")
}
deinit {
print("Car of the brand \(brand) is being deallocated")
}
}
class Owner {
var name: String
var car: Car?
init(name: String) {
self.name = name
print("Owner \(name) allocated")
}
deinit {
print("Owner \(name) deallocated")
}
}
do {
let tesla = Car(brand: "tesla")
let misterX = Owner(name: "Mister X")
tesla.owner = misterX
misterX.car = tesla
}
Araç nesnesinin artık bir Owner'a bağlı bir referansı vardır ve Owner'ın bir Otomobil için isteğe bağlı bir referansı vardır. Çıktı:
//Car of the brand tesla allocated
//Owner Mister X allocated
Güçlü referans döngüsü, ayrılma ve hafızayı boşaltmak için referans sayısının sıfıra ulaşmasını önler. Bu sorunu çözmek için weak referanslara ihtiyacımız var.
Weak
Güçlü referansların aksine weak, referans sayısını bir artırmaz. Böylece nesneyi ARC tarafından tahsis edilmekten koruyamazlar. Ayrılma durumunda zayıf referans otomatik olarak sıfır olarak ayarlanır. Tüm zayıf referansların isteğe bağlı değişkenleri değiştirmesinin nedeni budur. Bir sabiti zayıf olarak tanımlamak mümkün değildir.
Önceki örneğe bir göz atalım. Otomobille araç sahibi arasında zayıf bir referans kullanmak, yerinden çıkarma işleminin düzeltilmesine yardımcı olur:
class Car {
weak var owner: Owner?
...
}
class Owner {
weak var car: Car?
...
}
...
Şimdi ARC, tüm nesneleri doğru şekilde dağıtıyor:
//Car of the brand tesla allocated
//Owner Mister X allocated
//Owner Mister X deallocated
//Car of the brand tesla is being deallocated
Not: Her ikisi yerine Araba veya Sahip sınıfında yalnızca bir zayıf referans kullanılması sorunu da çözmüş ve güçlü referans döngüsünü çözmüştür.
Sahipsiz referanslar, zayıf olanlara benzer şekilde davranır. Tutulma sayısını da bir artırmazlar.Zayıf referanslardan farklı olarak, sahipsiz referansların bir İsteğe Bağlı Olması gerekmez; Sadece istenmeyen referansları kullanmanız, nesnenin ayarlandıktan sonra asla sıfır olmayacağını gerçekten bildiğiniz zaman önemlidir.
Apple’a göre, referansınızla referans kodun aynı anda kaldırılacağı zaman kullanmak en iyisidir.
Weak vs Unowned - Apple'dan bir öneri
"Bu referansın kullanım ömrü boyunca bir noktada sıfır olması geçerli olduğunda zayıf bir referans kullanın. Bunun tersine, referansın başlangıç sırasında ayarlandıktan sonra hiçbir zaman sıfır olmayacağını bildiğiniz zaman, Unowned bir referans kullanın."
Apple Documentation
Apple Documentation